直接和通过include定义嵌套类
假设我正在为我的家庭存储系统建模。 我有一堆不同类型的Container
,我发现它们中有很多都有装饰品,我已经为这种常见情况设置了一些辅助代码。
我的容器中有我的Mantlepiece
和我的Bookcase
。 我只把饰品存放在前者上; 而后者有所有的装饰品,精装书和软书。
这是一个初步尝试:
module Properties def has_ornament include OrnamentThings end module OrnamentThings module Things class Ornament end end end end class Container extend Properties end class Mantlepiece < Container has_ornament end class Bookcase < Container has_ornament module Things class Hardback end class Paperback end end end [Mantlepiece, Bookcase].each do |place| puts place.name puts place.constants.inspect puts place::Things.constants.inspect end # Output: # Mantlepiece # [:Things] # [:Ornament] # Bookcase # [:Things] # [:Hardback, :Paperback]
你可以看到Mantlepiece
正确地嵌套了Mantlepiece::Things::Ornament
; 但是Bookcase
的Things
声明意味着Bookcase::Things
只会嵌套Hardback
和Paperback
。 Bookcase::Things::Ornament
缺失。
我可以整齐地写这个,以便Bookcase
可以调用has_ornament
,然后声明它自己的一组Things
,并将它们全部嵌套在同一个命名空间中吗?
即使你的壁炉和书柜都有东西,但那些东西是不同的(因为它们包含不同的类别)。 所以他们不能只包括一些常见的Things
模块; 他们不得不定义自己独立的Things
,就像你在Bookcase
通过声明module Things
。
def has_ornament const_set(:Things, Module.new) unless const_defined? :Things, false self::Things.include OrnamentThings end module OrnamentThings class Ornament end end
这是有效的,因为Ruby允许您使用与声明它们相同的语法重新打开模块。 has_ornament
定义了一个全新的Things
模块,然后打开它以添加更多内容。 如果你在自定义之后调用has_ornament
,它会跳过创建并添加到你创建的模块中( false
确保我们只在当前类中查找Things
)。