类和继承

4

我正在尝试理解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初始化方法中的默认参数,是吗?
谢谢你的帮助!
5个回答

3
super(不带参数列表)调用与传递的相同参数的超类中的相同方法。如果要明确地传递没有参数,则必须使用空参数列表:super()
记住:super不是方法调用,它是一个关键字,关键字不必遵循正常的方法调用评估规则。这是其中的一个区别。对于方法调用,foofoo()是等效的,它们都不传递任何参数。对于super,存在一个区别:super()不传递任何参数,super 转发参数。
现在,这里有一个额外的转折:实际上,您initialize传递任何参数,那么它们是如何传递的...或者说是吗?嗯,事实证明,为了调用super,可选参数的默认值被视为已明确传递。

非常感谢您完整的答案!我以为它像其他方法一样! - Louis Etienne

2

super没有参数时,是一种快捷方式,可以传递与当前执行的方法相同的参数。在您的示例中,“bar”隐式传递给超类(这就是为什么两者都得到“bar”的原因)。

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

class User < Man
  attr_accessor :mail

  def initialize(name = "foo", mail = "bar")
    super(name)
    @mail = mail
  end
end

为什么你定义了两个参数?你可以使用无参的 super() 调用,这样你就可以从父类获取默认值。 - Lukas Baliak
@LukasBaliak,没错。但是如果我们想要定义它们的值而不是默认值呢?这种变化有一个优点。 - TechWisdom
没错,但他想知道为什么将名称定义为mail。当然,您可以使用此来“重新定义”名称变量。 在super()之后,您可以使用user.name =“新名称” - Lukas Baliak
@LukasBaliak,感谢您的反馈。我将澄清代码旨在提供一种可选解决方案。原因在前一句中已经解释:没有参数的super会使用当前函数的参数,无论它们如何被调用。至于您最后的建议——我认为这更像是一个解决方法,最好不要经常使用。如果您有一个参数,请传递它。不要让默认值发生并覆盖它。 - TechWisdom

0

你使用一个参数调用User类,在initialize内部,你使用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">

0

只需尝试这个,它会为您工作:

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

0

没有参数的super,会使用与自身调用相同的参数调用超类的初始化程序。你可以看到,因为name的值与mail相同。

你想要做的是:

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

通过使用括号,可以使用其他初始化程序的默认值,正如您所期望的那样。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接