【问题标题】:Class and inheritance类和继承
【发布时间】:2023-03-10 05:10:01
【问题描述】:

我正在尝试了解 Ruby 中的继承系统。这是我的代码:

class Man
  attr_accessor :name

  def initialize(name = "Foo")
    @name = name
  end
end

class User < Man
  attr_accessor :mail

  def initialize(mail = "bar")
    super
    @mail = mail
  end
end

这是我的测试:

man = Man.new
man
=> #<Man:0x007fb68da4a768 @name="Foo">

user = User.new
user
=> #<User:0x007fb68da442c8 @name="bar", @mail="bar">

我不明白为什么用户的@name 不是“Foo”!正常的,应该是因为这是man的initialize方法中的默认参数,不是吗?

感谢您的帮助!

【问题讨论】:

    标签: ruby oop inheritance


    【解决方案1】:

    super 不带参数,调用超类的初始化器,参数与调用它自身的参数相同。可以看到,因为 name 和 mail 的值一样。

    你想做的是:

    def initialize(mail = "bar")
      super()
      @mail = mail
    end
    

    如您所愿,通过使用方括号,将使用其他初始化程序的默认值。

    【讨论】:

      【解决方案2】:

      super 不带参数是传递与当前执行方法相同的参数的快捷方式。在您的示例中,“bar”被隐式传递给超类(这就是为什么您为它们都获得“bar”)。

      避免混淆的可选解决方案:

      class User < Man
        attr_accessor :mail
      
        def initialize(name = "foo", mail = "bar")
          super(name)
          @mail = mail
        end
      end
      

      【讨论】:

      • 为什么要定义两个参数?您可以在没有参数的情况下调用 super() 并从 Parent 类获得默认值
      • @LukasBaliak,没错。但是如果我们想同时定义它们而不是默认值呢?这种变化有一个优势。
      • 没错,但他想明白为什么这个名字被定义为邮件。 Ofc 您可以使用它来“重新定义”名称 var。在super() 之后可以使用user.name = "new name"
      • @LukasBaliak,感谢您的反馈。我将澄清该代码旨在为可选解决方案提供建议。上一句解释了原因:不带参数的 super 获取当前函数参数,无论它们如何被调用。至于最后你的建议 - 我认为它更像是一种解决方法,你最好不要使用很多。如果你有一个参数 - 传递它。不要让默认值发生然后覆盖它。
      【解决方案3】:

      试试这个,它会为你工作:

      class Man
        attr_accessor :name
      
        def initialize(name = "Foo")
          @name = name
        end
      end
      
      class User < Man
        attr_accessor :mail
      
        def initialize(mail = "bar")
          super()
          @mail = mail
        end
      end
      
      man = Man.new
      puts man.name  #> Foo
      user = User.new
      puts user.name  #> Foo
      

      【讨论】:

        【解决方案4】:

        您使用一个参数调用 User 类,并在初始化内部调用具有相同参数 bcs 的父类。你像这样使用super

        如果你调用super(),你不会发送参数,因为你调用了没有参数的父初始方法。

        喜欢这个

        class Man
          attr_accessor :name
        
          def initialize(name = "Foo")
            @name = name
          end
        end
        
        class User < Man
          attr_accessor :mail
        
          def initialize(mail = "bar")
            super()
            @mail = mail
          end
        end
        
        Man.new
        # => #<Man:0x52a7e380 @name="Foo">
        User.new
        # => #<User:0x11777eb0 @mail="bar", @name="Foo">
        

        【讨论】:

          【解决方案5】:

          super(没有参数列表)使用传入的相同参数调用超类中的相同方法。如果您想显式传递no参数,您必须使用空参数列表:super()

          记住:super 不是方法调用,它是关键字,关键字不必遵循正常的方法调用评估规则。这是其中的差异之一。对于方法调用,foofoo() 是等价的,它们都没有传递任何参数。对于super 有所不同:super() 不传递参数,super 转发参数。

          现在,这里有一个额外的转折:实际上,您将任何参数传递给initialize,那么它们是如何传递的......或者你呢?好吧,事实证明,为了调用 super,可选参数的默认参数被视为已显式传递。

          【讨论】:

          • 非常感谢您的完整回答!我认为这是一种和其他方法一样的方法!
          猜你喜欢
          • 2015-12-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多