为什么模块的单例方法在混合的下游特征类中不可见? [英] Why a module's singleton method is not visible in downstream eigenclasses where it gets mixed?
问题描述
我理解常规方法查找路径,即类,超类/模块,一直到BasicObject
。我认为链的单例版本也是如此,但是当您在元链中混合模块时似乎并非如此。我很感激如果有人能解释为什么在以下示例中 Automobile
模块的 banner
方法被调用而不是单例版本当我把这个模块包含在Vehicle的本征类中时。
I understand the regular method lookup path i.e. class, superclass/module, all the way up to BasicObject
. I thought it was true for singleton version of the chain also but doesn't seem the case when you mixin a module in the meta-chain. I'd appreciate if someone can explain why in the following example Automobile
module's banner
method is called instead of its singleton version when I have included this module in Vehicle's eigenclass.
module Automobile
def banner
"I am a regular method of Automobile"
end
class << self
def banner
"I am a singleton method of Automobile"
end
end
end
class Vehicle
def banner
"I am an instance method of Vehicle"
end
class << self
include Automobile
def banner
puts "I am a singleton method of Vehicle"
super
end
end
end
class Car < Vehicle
def banner
"I am an instance method of Car"
end
class << self
def banner
puts "I am a singleton method of Car"
super
end
end
end
puts Car.banner
# I am a singleton method of Car
# I am a singleton method of Vehicle
# I am a regular method of Automobile
推荐答案
首先,包括
不包括你所期望的本征类方法。考虑:
First of all, include
does not include eigenclass methods as you might expect. Consider:
module Foo
class << self
def do_something
puts "Foo's eigenclass method does something"
end
end
end
module Bar
include Foo
end
puts Bar.do_something
# undefined method `do_something' for Bar:Module (NoMethodError)
请注意,这与经典定义的类方法的行为一致:
Note that this is consistent with the behavior of classically defined class methods:
module Foo
def self.do_something
puts "Foo's class method does something"
end
end
module Bar
include Foo
end
puts Bar.do_something
# undefined method `do_something' for Bar:Module (NoMethodError)
一个常见的习惯用法是在子模块中定义类方法,然后在包含模块时触发对 extend
的调用:
A common idiom is to define the class methods in a submodule and then trigger a call to extend
when the module is included:
module Foo
def self.included(base)
base.extend ClassMethods
end
module ClassMethods
def do_something
puts "Foo::ClassMethod's instance method does something"
end
end
end
module Bar
include Foo
end
puts Bar.do_something
# Foo::ClassMethod's instance method does something
要注意的第二件事是,你真的将 Automobile
的实例方法包含在<$ c $的本征类中c> Vehicle ,因此 Automobile
的实例方法变为 Vehicle $ c $的(本征)类方法c>。
The second thing to note is, that you are really including the instance methods of Automobile
into the eigenclass of Vehicle
, thus the instance methods of Automobile
turn into (eigen)class methods of Vehicle
.
你的 Car
类基本上与这一切无关。这里唯一需要注意的是,类继承也使类方法可用,而 include
则不然。示例:
Your Car
class basically has nothing to do with all this. The only thing to note here is, that class inheritance also makes class methods available, whereas include
does not. Example:
class Foo
def self.do_something
puts "Foo's class method does something"
end
end
class Bar < Foo
end
puts Bar.do_something
# "Foo's class method does something"
这篇关于为什么模块的单例方法在混合的下游特征类中不可见?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!