让“super”通过包含的模块调用父类

glo*_*esk 5 ruby inheritance superclass

我有Boy继承 class 的类Person,并包含 module Bipedal。和Person都有.Bipedal#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
Run Code Online (Sandbox Code Playgroud)

由于该Bipedal模块包含在 中BoyBipedal#two_legs因此优先于Person#two_legs. 当我调用super实例时Boy,模块Bipedal优先于父类Person

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

我想在一个地方使用一个版本,在另一个地方使用另一个版本。Bipedal还有其他东西,所以我无法评论include Bipedal。是否有一些标准方法可以让Boy#two_legssuper使用父类版本而不是模块版本,如下所示?

johnny.two_legs
# >> "Johnny has two human legs."
Run Code Online (Sandbox Code Playgroud)

我想出了这个:

Boy.superclass.instance_method(:two_legs).bind(self).call(@name)
Run Code Online (Sandbox Code Playgroud)

它可以代替super(@name),但比我预期的更复杂。

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

Car*_*and 3

人们可以使用Method#super_method方法两次。这是一种普通的 Ruby 方法,我相信它有资格作为让Boy#two_legsinvokePerson#two_legs而不是Bipedal#two_legs.

class Boy < Person
  include Bipedal
  attr_accessor :name
  def initialize(name)
    @name = name
  end
  def two_legs
    method(:two_legs).super_method.super_method.call(@name)
  end
end

willie = Boy.new('Willie')
willie.two_legs
Willie has two human legs.
Run Code Online (Sandbox Code Playgroud)

请注意以下事项。

willie.method(:two_legs).super_method.owner
  #=> Bipedal
willie.method(:two_legs).super_method.super_method.owner
  #=> Person
Run Code Online (Sandbox Code Playgroud)