我理解常规方法查找路径,即class, superclass/module, all the way up to BasicObject
。我认为对于单链版本的链也是如此,但是当您在元链中混合模块时似乎并非如此。我很感激,如果有人可以解释为什么在下面的示例中Automobile
模块的banner
方法被调用而不是单例版本,当我将此模块包含在Vehicle的本征类中时。
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
答案 0 :(得分:8)
首先,include
不包含您所期望的本征类方法。考虑:
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)
请注意,这与经典定义的类方法的行为一致:
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
的调用:
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
的实例方法包含在Vehicle
的本征类中,因此Automobile
的实例方法转换为(本征)类Vehicle
的方法。
你的Car
课程基本上与这一切无关。这里唯一需要注意的是,类继承也使类方法可用,而include
则不然。例如:
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"
答案 1 :(得分:2)
首先,类是一个对象,就像其他对象一样,它也有自己的超类;
第二,Eigenclass本身是一个普通的类,只有匿名和sorta隐形;
第三,派生类的特征类的超类是基类的本征类;
第四,include
包括所包含模块的实例方法(不是单例方法),使它们成为接收器类对象的实例方法。
您的示例中有两个并行的继承链
Car&lt;车辆&lt; ...
汽车的本征类&lt;车辆的本征类&lt;汽车&lt; ...
在irb上进行以下测试:
class Object
def eigenclass
class << self
self
end
end
end
Car.ancestors # => [Car, Vehicle, Object, Kernel, BasicObject]
Car.eigenclass.ancestors # => [Automobile, Class, Module, Object, Kernel, BasicObject]
Vehicle.eigenclass.ancestors # => [Automobile, Class, Module, Object, Kernel, BasicObject]
Car.eigenclass.superclass.equal? Vehicle.eigenclass # => true
您看,Automobile
位于本征类继承链中。但令人遗憾的是,ancestor
方法并没有返回不可见的本征类,但它们实际上是在第二个链中。