Search code examples
rubyclassmoduleumlnotation

Notation to distinguish class inheritance and module inclusion


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?


Solution

  • 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"