Допустим, у меня есть трехуровневая иерархия классов наследования:
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
)? Это кажется мне более грязным ...