Tuesday, July 24, 2012

Ruby module inheritance

Another frequently-used Ruby technique.

When building up a data model, it is not unusual to generate two modules that represent the abstract ModelItem (base) class : a ModelItemClass module to be extended by all ModelItem (derived) classes, and a ModelItemObject module to be included by all ModelItem (derived) classes.

But what happens when these ModelItem modules themselves need to mix-in other modules? For example, to support serialization, the ModelItemClass and ModelItemObject might need to include the modules JsonClass and JsonObject, respectively.

When the abstract base classes are already represented by distinct Class and Object modules, it becomes trivial to extend these : a module can be included in a module, and its (instance) methods will be added when that module is subsequently included or extended by a derived class.

Some quick experimentation in irb will demonstrate that this works as expected:

module AClass
  def a; puts "a class method"; end

module AObject
  def a; puts "a instance method"; end

module BClass
  include AClass
  def b; puts "b class method"; end

module BObject
  include AObject
  def b; puts "b instance method"; end

class B
  extend BClass
  include BObject

B.a   # -> "a class method"
B.b  # -> "b class method"
B.new.a # -> "a instance method"
B.new.b #-> "b instance method"

No comments:

Post a Comment