在方法重定义中访问超类方法时出现问题
我有点难以理解什么时候可以调用“super”,什么时候不能调用。在下面的示例中, super 方法会导致无超类错误。
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 的一个实例吗?我是否没有像上面的细菌示例那样重新定义现有方法?
I am having a bit trouble to understand when "super" can be called and when not. In the below example the super method leads to a no superclass error.
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
But this works:
class Fixnum
def times
super # -> works
puts "done"
end
end
5.times { |i| puts i.to_s }
Is 5 not just also an instance of Fixnum. And am I not redefining an existing method like in the Bacterium example above?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不,不是真的。
Fixnum
继承自Integer
类,并且您实际上覆盖了Integer#times
,因此super
可以正常工作,因为它从父级调用实现。为了在monkeypatching时实现类似的效果,您应该在重新定义方法之前对其进行别名,并通过别名调用它。
类重新打开不是继承的一种形式,并且
super
在那里没有任何用处。No, not really.
Fixnum
inherits fromInteger
class, and you are in fact overridingInteger#times
, sosuper
works, as it calls implementation from the parent.In order to achieve something similar when monkeypatching, you should alias method before redefining it, and there call it by alias.
Class reopening is not a form of inheritance and
super
is of no use there.正如 Mladen 所说,您可以使用
Class#superclass
检查:Integer 是否实现了
#times
?:是的。
因此,以一种简化的方式,我们可以说 super 调用超类中的方法。在您的例子中,
Bacterium
的超类是 Object,它不实现#eats
。我说这是非常简化的,因为看这个例子:
别认真对待我在这里写的内容,它实际上是 Ruby 对象模型的冰山一角,理解这一点很重要(我还在学习它) -那么你就会得到大部分或全部这些概念。
使用一些 Google-fu 来表示“Ruby 对象模型”...
Just as Mladen said, and you can check that with
Class#superclass
:And does Integer implement
#times
?:Yes it does.
So, in a simplified way, we can say, that super invokes the method you are in of a superclass. In your case the superclass of a
Bacterium
is Object, which doesn't implement#eats
.I said this is very simplified, because look at this example:
Don't take to serious what I wrote here, it is actually tip of the iceberg of the Ruby object model, which is important to understand (I am still learning it) - then you will get most, or all of those concepts.
Use some Google-fu for "Ruby object model"...