module Country
def location
puts "location"
end
def self.included(base)
def cities
puts "cities"
end
end
def self.extended(base)
def animals
puts "animals"
end
end
end
class Test
include Country
end
class Test2
extend Country
end
据我所知,当将模块作为实例方法包含时将调用self.included,而当将模块作为静态类方法扩展时将调用self.extended。
但是当我在同一个文件中有两个类时,为什么不抛出错误
Test.new.animals
=>动物
并且如果我删除了Test 2类,
# class Test2
# extend Country
# end
Test.new.animals
=>没有方法错误
def bar
,没有明确的definee(即def foo.bar
)在最接近的词法包围模块中定义bar
。对于您的所有def
而言,最接近的词法包围模块始终是Country
,因此,这三种方法都在Country
模块中定义。
单一方法
,则可以使用module Country
def self.extended(base)
def base.animals
puts "animals"
end
end
end
请参见Ruby what class gets a method when there is no explicit receiver?以获取更多详细信息。
module Country
def location
puts "location"
end
def self.included(base)
def cities
puts "cities"
end
end
def self.extended(base)
puts "#{self}" ## NOTICE THIS NEW LINE! NEW LINE
def animals
puts "animals"
end
end
end
class Test
include Country
end
class Test2
extend Country
end
Test.new.animals
怎么了?
关键是在动物方法上方添加puts "#{self}
行。
我们可以在此处看到动物方法是在国家/地区中定义的模块。所以说真的,当您认为自己正在扩展时,就意味着确保将其添加为实例方法,而不是添加“静态类方法”(如果您来自c#/ java背景)。严格来说,这不是准确的:当您像这样“扩展”时-如果您做得正确-实际上是在添加方法到Test2的单例类。在这方面,Ruby的对象模型有些棘手。静态类方法是添加到类的单例类中的方法。什么是单身人士班?现在,您将进入ruby的对象模型。它很复杂并且有点人才流失,但是一旦掌握了它,就可以做一些非常有力的(而且是危险的?)事情,例如:猴子修补。
解决方案:
def base.animals
。