在方法重定义中访问超类方法时出现问题

发布于 2024-10-07 07:13:31 字数 460 浏览 6 评论 0原文

我有点难以理解什么时候可以调用“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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

相思故 2024-10-14 07:13:31

不,不是真的。 Fixnum 继承自 Integer 类,并且您实际上覆盖了 Integer#times,因此 super 可以正常工作,因为它从父级调用实现。

为了在monkeypatching时实现类似的效果,您应该在重新定义方法之前对其进行别名,并通过别名调用它。

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

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

No, not really. Fixnum inherits from Integer class, and you are in fact overriding Integer#times, so super 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 Bacterium
  alias_method :eats_original, :eats
  def eats
    eats_original # -> "Nam"
    puts "Yam"
  end
end

Class reopening is not a form of inheritance and super is of no use there.

如果没结果 2024-10-14 07:13:31

正如 Mladen 所说,您可以使用 Class#superclass 检查:

irb> Fixnum.superclass
=> Integer

Integer 是否实现了 #times?:

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

是的。

因此,以一种简化的方式,我们可以说 super 调用超类中的方法。在您的例子中,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 对象模型的冰山一角,理解这一点很重要(我还在学习它) -那么你就会得到大部分或全部这些概念。

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

Just as Mladen said, and you can check that with Class#superclass:

irb> Fixnum.superclass
=> Integer

And does Integer implement #times?:

irb> Integer.instance_methods.grep /times/
=> [: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:

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!!

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"...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文