Methods

By default, all methods are inherited from all superclasses. Any of the superclasses' methods can be uninherited, as described earlier, by using the uninherit/1 directive.

If the same message is defined for more than one superclass, however, you must choose at most one method to inherit for the message. You may choose none. You may do this by defining a new method for the message (shadowing the superclasses' methods), or by using the uninherit/1 directive, or by using the inherit/1 directive.

The following is considered a classic example of multiple inheritance.

     :- class toy.             % no slots in this class
     
     Self >> size(small).
     
     Self >> rolls(false).
     
     :- end_class toy.
     
     :- class truck.         % no slots in this class
     
     Self >> size(large).
     
     Self >> rolls(true).
     
     :- end_class truck.
     

The idea expressed in these definitions is that most toys are small and do not roll. On the other hand, most trucks are large, but they do roll. A toy truck shares one feature with each class, but we can hardly expect a compiler to choose the correct one.

The definition of a new class, toy_truck, might begin with

     :- class toy_truck = toy + truck.
     

Rather than redefine the get methods for size and rolls, we can specify which to inherit in two ways. One way is positive, stating which to inherit, and the other way is negative, stating which not to inherit.

The positive version would be

     :- inherit
             toy >> (size/1),
             truck >> (rolls/1).
     

This is more convenient when a message is defined in several superclasses, because all but the chosen method are uninherited. And, it is probably easier to understand.

The negative version would be

     :- uninherit
             toy >> (rolls/1),
             truck >> (size/1).
     

The toy_truck class would exhibit the same behavior with either definition.

It is possible to define methods that access the shadowed or uninherited methods of the superclasses, by sending the message to the superclasses. In the case of multiple inheritance, however, it may be necessary to specify which superclass to send the message to.

The toy_truck class, for example, might define these methods:

     Self >> uninherited_size(S) :-
             super(truck) >> size(S).
     
     Self >> uninherited_rolls(R) :-
             super(toy) >> rolls(R).
     

They provide access to the unchosen methods from toy_truck's superclasses.

While these examples with the toy_truck class are clearly "toy" examples, the same techniques can be used in more realistic cases.