When the ancestors of a module are displayed, for example with String
:
String, Comparable, Object, Kernel, BasicObject
some of them (String, Object, BasicObject) are classes and others are not. Is there a notation to distinguish them? A possible candidate that came to mind was to use <<
instead of <
for module inclusion:
String << Comparable < Object << Kernel < BasicObject
or conversely for class inheritance:
String < Comparable << Object < Kernel << BasicObject
but I am not sure. If there is no notation already out there, what do you think about the above? How is this expressed in UML?
There is no such notation that I know of.
For the most part, though, I don't think one is necessary. In general (there are likely caveats here, but I can't think of any right now), once a module is part of the ancestor chain, it behaves just like a class in the ancestor chain. To use your String example, ''.is_a? Comparable
returns true
and you calling super
in a method within String that Comparable defines will call Comparable's implementation.
The only difference is with regard to initialize
, since you can't create an instance of a Module.
As for UML, given this, it can just be a normal ancestor just like a class (I think), as I don't believe UML has any way different way of representing modules.
Personally, I think your proposed notation is a bit hard to parse, and when I do care would rather just see it all spelled out:
a = String.ancestors
a.map{ |c| c.class.to_s.downcase }.zip(a).map { |o| o.join(' ') }.join(' < ')
#=> "class String < module Comparable < class Object < module PP::ObjectMixin < module Kernel < class BasicObject"