假设我有一个三级继承类层次结构:
Building
⬑ OfficeTower
⬑ House
⬑ RowHouse
⬑ DetachedHouse
我希望OfficeTower
和House
类从Building
类继承一个类方法,该方法将列出所有子类。我只想在Building
类中定义一次此方法,但是我实际上不希望该方法是公开可用的,如果直接从Building
类。
这是我尝试过的:
class Building
private
def self.subclasses
# list all subclasses
ObjectSpace.each_object(Class).select { |c| c < self }
end
end
class OfficeTower < Building
end
class House < Building
end
class RowHouse < House
end
class DetachedHouse < House
end
在subclasses
的子类上调用时,Building
类方法可以正常工作:
House.subclasses
=> [DetachedHouse, RowHouse] # This is good.
我期望直接从subclasses
类调用时,NoMethodError
方法会引发Building
。但这没有发生:
Building.subclasses
=> [DetachedHouse, OfficeTower, RowHouse, House] # I expected NoMethodError!
在这种情况下,为什么private
不起作用?从Building
类直接调用时,是否有更好的方法使此方法不可用?我是否应该在这里使用组合而不是继承(即使用Buildable
类方法创建一个subclasses
模块,并将该模块包含在OfficeTower
和House
中)?这让我感到更加混乱...
答案 0 :(得分:3)
为什么在这种情况下不进行私人工作?
因为private
仅影响实例方法,而不影响类方法。我通常为此使用private_class_method
private_class_method def self.subclasses
# list all subclasses
ObjectSpace.each_object(Class).select { |c| c < self }
end
或者,您可以在单例类中定义此方法,该方法将作为实例方法。
class << self
private
def subclasses
# list all subclasses
ObjectSpace.each_object(Class).select { |c| c < self }
end
end
请注意,私有性是继承的,您也将无法在House
上调用该方法。如果self
是Building
def self.subclasses
raise 'use a subclass' if self == Building
# list all subclasses
ObjectSpace.each_object(Class).select { |c| c < self }
end