2

我很难理解什么时候可以调用“super”,什么时候不可以。在下面的示例中,super 方法导致 no superclass 错误。

class Bacterium
  def eats
    puts "Nam"
  end
end

class Bacterium
  def eats
    super # -> no superclass error
    puts "Yam"
  end
end

b = Bacterium.new
b.eats

但这有效:

class Fixnum
  def times
    super # -> works
    puts "done"
  end
end

5.times { |i| puts i.to_s }

5 不仅是 Fixnum 的一个实例。我不是像上面的细菌示例那样重新定义现有方法吗?

4

2 回答 2

4

不,不是。FixnumInteger类继承,而您实际上是在覆盖Integer#times,因此super有效,因为它从父级调用实现。

为了在monkeypatching时达到类似的效果,您应该在重新定义它之前给方法起别名,并通过别名调用它。

class Bacterium
  alias_method :eats_original, :eats
  def eats
    eats_original # -> "Nam"
    puts "Yam"
  end
end

类重新打开不是一种继承形式,super在那里没有用处。

于 2010-12-13T07:23:49.837 回答
3

正如 Mladen 所说,您可以使用以下命令进行检查Class#superclass

irb> Fixnum.superclass
=> Integer

整数是否实现#times?:

irb> Integer.instance_methods.grep /times/
=> [:times]

是的,它确实。

所以,以一种简化的方式,我们可以说,super 调用了你所在的超类的方法。在您的情况下,a 的超类Bacterium是 Object,它没有实现#eats.

我说这很简化,因为看这个例子:

module One
  def hi
    " World" << super()
  end
end

module Two
  def hi
    "Hello" << super()
  end
end

class SayHi
  def hi
    "!!!"
  end
end

h = SayHi.new
h.extend(One)
h.extend(Two)

puts h.hi

#=> Hello World!!

不要认真我在这里写的东西,它实际上是 Ruby 对象模型的冰山一角,理解这一点很重要(我还在学习它)——然后你会得到大部分或所有这些概念。

对“Ruby 对象模型”使用一些 Google-fu...

于 2010-12-13T09:30:30.587 回答