Одинаковая модель наследования в нескольких классах
У меня следующая ситуация:
class A < CommonParent
... some code ...
class IdenticalDescendent < self
identical_statement_0
identical_statement_1
end
end
class B < CommonParent
... some other code ...
class IdenticalDescendent < self
identical_statement_0
identical_statement_1
end
end
У меня много такой ситуации. Мол, около сорока IdenticalDescendent
занятия в моем приложении. Мне нравится шаблон, он позволяет мне звонить A::IdenticalDescendent
или же B::IdenticalDescendent
или что-то еще, чтобы получить доступ к определенным связанным поведениям в разных доменах A
или же B
). По причинам, я не могу просто полностью абстрагировать проблему, перепроектировав кластеризацию поведения.
Итак, общая форма моего вопроса - как мне автоматизировать генерацию IdenticalDescendent во всех этих случаях. Есть потомки CommonParent
которые не вызывают этот паттерн, поэтому действия, вероятно, не должны происходить там. Я предполагаю, что это должно произойти в миксе или что-то в этом роде, но я нахожу это, если я просто пытаюсь сделать
class A < CommonParent
include CommonBehaviour
... some code ...
end
module CommonBehaviour
... what ...
end
Я не могу понять, как писать CommonBehaviour
чтобы позволить IdenticalDescendent спуститься из включающего класса.
Помоги мне, Stackru, ты моя единственная надежда.
3 ответа
Я полагаю, что вы можете автоматизировать свой шаблон с помощью функции обратного вызова (хука) Class # наследуется:
class CommonParent
def self.inherited(klass)
return unless klass.superclass == CommonParent
klass.const_set(:Descendent, Class.new(klass) do
def x
puts "in x"
end
end)
end
end
class A < CommonParent
def a
puts "in a"
end
end
d = A::Descendent.new #=> #<A::Descendent:0x007f99620172e8>
d.a # in a
d.x # in x
class B < CommonParent
def b
puts "in b"
end
end
d = B::Descendent.new #=> #<B::Descendent:0x007f99618b18f0>
d.b # in b
d.x # in x
d.a #=> NoMethodError:... (as expected)
Обратите внимание, что без:
return unless klass.superclass == CommonParent
создание A::Descendent
вызовет inherited
с klass => Descendent
, вызывая анонимный подкласс Descendent
быть созданным и т. д., что приводит к "слишком глубокому исключению на уровне стека".
Ответ, который я искал, должен использовать блочную нотацию для Class.new
внутри self.included
Перезвоните. У меня есть это сейчас:
module CommonDescendant
def self.included(base)
descendant_class = Class.new(base) do
... put my desired common behavior here ...
end
base.const_set :Descendant, descendant_class
end
end
class A
include CommonDescendant
... unique behavior ...
end
class B
include CommonDescendant
... unique other behavior ...
end
И это дает нам дизайн, который я хочу!
Я бы предложил разделить класс потомков и генерацию методов. Конечно, вы можете бросить все в class_eval
блок (который положительно пахнет).
Что-то вроде следующего (полностью не проверено)
module CommonDescendants
Descendant = Class.new(self) do
include CommonDescendantMethods
end
end
module CommonDescendantMethods
end
class A < CommonParent
extend CommonDescendants
end