我可以将父类方法设为私有,但允许子类仅通过继承来调用它们吗?

时间:2019-10-30 16:38:40

标签: ruby inheritance

假设我有一个三级继承类层次结构:

Building
  ⬑ OfficeTower
  ⬑ House
    ⬑ RowHouse
    ⬑ DetachedHouse

我希望OfficeTowerHouse类从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模块,并将该模块包含在OfficeTowerHouse中)?这让我感到更加混乱...

1 个答案:

答案 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上调用该方法。如果selfBuilding

,我将把方法公开,并从中提出
  def self.subclasses
    raise 'use a subclass' if self == Building

    # list all subclasses
    ObjectSpace.each_object(Class).select { |c| c < self }
  end
相关问题