ruby - 让 `super` 通过包含的模块调用父类

标签 ruby inheritance superclass

我有继承类 Person 的类 Boy,并包含模块 BipedalPersonBipedal 都有 #two_legs 的版本。

module Bipedal
  def two_legs(name)
    puts "#{name} has exactly two limbs used for walking."
  end
end

class Person
  def two_legs(name)
    puts "#{name} has two human legs."
  end
end

class Boy < Person
  include Bipedal
  attr_accessor :name
  def initialize(name)
    @name = name
  end

  def two_legs
    super(@name)
  end
end

因为 Bipedal 模块包含在 Boy 中,所以 Bipedal#two_legs 优先于 Person#two_legs .当我在 Boy 实例上调用 super 时,模块 Bipedal 优先于父类 Person

johnny = Boy.new('Johnny')
johnny.two_legs
# >> "Johnny has exactly two limbs used for walking."

我想在一个地方使用一个版本,在另一个地方使用另一个版本。 Bipedal 还有其他东西,所以我不能注释掉 include Bipedal。有没有一些标准的方法让 Boy#two_legssuper 使用父类版本而不是模块版本,如下所示?

johnny.two_legs
# >> "Johnny has two human legs."

我想到了这个:

Boy.superclass.instance_method(:two_legs).bind(self).call(@name)

代替 super(@name) 工作,但比我预期的要复杂。

同样,问题是,在调用 super 时,是否有一种标准方法可以强制父类优先于模块?

最佳答案

不,没有标准方法强制调用 super 以特定顺序遍历祖先。他们按照预定义的顺序走。看看the documentation on calling methods :

When you send a message, Ruby looks up the method that matches the name of the message for the receiver. Methods are stored in classes and modules so method lookup walks these, not the objects themselves.

Here is the order of method lookup for the receiver's class or module R:

  • The prepended modules of R in reverse order
  • For a matching method in R
  • The included modules of R in reverse order

If R is a class with a superclass, this is repeated with R's superclass until a method is found.

Once a match is found method lookup stops.

由于您的类 Boy 直接包含模块 Bipedal,并且由于在父类(super class)之前搜索包含的模块,并且一旦找到匹配项就停止搜索,父类(super class) Person 永远不会被检查。

使用refinements时也是如此因为查找总是在检查父类(super class)之前命中包含的模块。

如果您将 include Bipedal 移动到 Person 类中,那么它将按照您期望的方式工作,因为 Boy 不直接包含模块,所以它最终会搜索父类(super class),在那里它会找到定义的方法。

您可能还有其他创造性的方法可以实现此目标,例如您提供的 Boy.superclass... 示例,但您询问是否可以在调用 时更改查找行为super,根据文档,答案不是。

关于ruby - 让 `super` 通过包含的模块调用父类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53491282/

相关文章:

Android Class.getGenericSuperclass 返回 java.lang.Object

ruby-on-rails - 如何搜索查询结果,以防止发出太多请求

sql - 包含和条件未给出预期 SQL 的 ActiveRecord 查询

c++ - 指针向下转换和向上转换的用法区别?

python - Python中的继承和init方法

c++ - 澄清 Sean Parent 的谈话 "Inheritance is the base class of evil"

java - 子类和父类(super class)

java - 当调用super方法时,i指的是什么?

ruby-on-rails - Rails 应用程序的入口点在哪里?

ruby-on-rails - 'gem 安装' 和 'sudo gem install'