为什么我们要在Ruby的类中放一个模块?
在Ruby中,为了命名空间的缘故,我发现将模块放在模块内可能很有用。 我也看到可以将模块放在类中。 但我不明白你为什么这么做。
模块通常被混合到类中,对吗? 那么,在类中定义模块的目的是什么?
我们可以在编写像这样的类猿代码时使用它:
class DrugDealer
module Drug
def happy?; true; end
end
def approach(victim)
victim.extend Drug
end
end
o = Object.new
DrugDealer.new.approach(o)
o.happy? # => true
在现实世界中更实际的另一个例子是混合只应用于子类。
当某个事物的某些方面适用于某些子类并且其他方面适用于其他子类时,这非常有用,但这些方面没有足够的顺序来为清晰的类层次结构(树)开路。 想想多重继承! 一个简单的例子:
class Person
def handshake
:sloppy
end
def mind_contents
:spam
end
module Proper
def handshake
:firm
end
end
module Clever
def mind_contents
:theories
end
end
end
class Professor < Person
include Proper
include Clever
# ...
end
等等。 一种很好的,当用于明智的。 即使是超级调用和构造函数(我没有在这里定义),按照我希望的方式流过所有混合类和类。
class Image
module Colors
Red = ...
Blue = ...
end
include Colors
end
include Image::Colors
Image.new.set_pixel x, y, Red
我已经在具有复杂命名空间的大型Rails应用中遇到了一个用例。 一个简单的例子:
# app/models/invoice/dependents/item.rb
class Invoice
module Dependents
class Item
# Define invoice item
end
end
end
这里的Invoice
是它自己的一个类,但是它的依赖项也是一个很好的名字空间。 我们不能说module Invoice
因为该常量已经被定义为一个类,但是我们仍然可以使用它作为一个名称空间。
巨人警告
如果您使用类作为命名空间,并且您正在使用Rails,请确保您不会意外地在其他地方声明该类 。 自动加载会毁了你的一天。 例如:
# app/helpers/invoice/dependents/items_helper.rb
class Invoice # This line will cause you grief
module Dependents
module ItemsHelper
# view helper methods
end
end
end
在此文件中声明class Invoice
的事实会创建加载顺序依赖性; 如果此文件的class Invoice
行在您想要的类定义之前执行,则您的预期类定义可能无法正常工作 。 在这个例子中,如果Invoice
已经声明没有父类,我就不能声明这个Invoice
sublcasses ActiveRecord::Base
。
你可以在另一个文件的顶部需要你的“真实”类定义文件,但至少在Rails自动加载的情况下,如果你这样做,你将不会有更多的争论:
# app/helpers/invoice/dependents/items_helper.rb
module Invoice:Dependents::ItemsHelper
# view helper methods
end
使用这种语法,Rails将看到Invoice
常量并使用自动加载来查找它,并在您的模型文件中找到它并按照您的意图进行定义。