I have the following situation:
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
I have this situation a lot. Like, there are about forty IdenticalDescendent
classes in my app. I like the pattern, it allows me to call A::IdenticalDescendent
or B::IdenticalDescendent
or whatever to access certain related behaviours in different domains (specified by A
or B
). For reasons, I can't just completely abstract the problem away by re-designing the behaviour clustering.
So the general form of my question is how do I automate the generation of IdenticalDescendent in all of these. There ARE descendants of CommonParent
that don't invoke this pattern, so the action probably shouldn't happen there. I imagine it should happen in a mixin or something, but I find that if I just try to do:
class A < CommonParent
include CommonBehaviour
... some code ...
end
module CommonBehaviour
... what ...
end
I can't figure out how to write CommonBehaviour
to allow for the IdenticalDescendent to descend from the including class.
Help me StackOverflow, you're my only hope.
I believe you can automate your pattern by using the callback (hook) Class#inherited:
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)
Note that, without:
return unless klass.superclass == CommonParent
the creation of A::Descendent
would trigger inherited
with klass => Descendent
, causing an anonymous subclass of Descendent
to be created, etc., resulting in a "stack level too deep exception."