Multiple inheritance refers to the ability of a class to have more
than a single superclass. Several languages provide multiple
inheritance; equally many languages provide only single
inheritance, possibly with `interface inheritance' constructs like
Objective-C's protocols and Java's interfaces. C++, in all its
baroqueness, provides both multiple inheritance, plus inheritance
of interface through signatures.
Suppose the class
D has both
C as a superclass. What effect does this have?
A class with instances that carry state (i.e., instance variables)
must be a subclass of the
- Any state defined for instances of
also present in instances of
D. There is no sharing
of slots based on the name of instance variables as in CLOS.
Thus, every instance variable i consuming space in an
C, also consumes space
in an instance of
- Every method defined for
B is also defined for
D. Obviously, every method defined for
C is also defined for
- If both
C define the same method
foo, a method clash is said to have occured, and
D should provide its own implementation of that
method. This is not mandatory; it is not checked by the compiler;
it is optionally checked by the resolver. If a method clash is
not resolved, a
program-condition is raised when the
method is invoked at run time.
State class. If both
C maintain state, they must both
State, which brings up the issues
involving repeated inheritance. Actually, these issues are mild
in TOM when compared to the same issues in languages like C++ or
Eiffel. To sum it up: repeated inheritance is shared inheritance.
- With respect to instance variables, things remain the same: every
instance variable declared in a superclass gets its spot in the
D only has one
instance variable (inherited from
State), even though
it `is inherited twice'.
- If a method
foo is defined by
B, and redefined by
C, it is
the redefinition of
C that is applicable to
D. The implementation by
State that `is
visible' through the inheritance of
B is nulled by it
being overriden in the inheritance path through
super is performing an invocation of a
method as provided by a superclass. Usually, the method is
invoked from the method that overrides the original definition.
For example, the following is not uncommon for an initializer:
If a class has multiple superclasses, the message to super must
indicate which superclass is to provide the method implementation.
If the super message is unambiguous, the compiler will make the
obvious choice, that can be described as follows: Suppose class
my_counter = 1;
= [super init];
D overrides the method
init as described
above. Imagine a class
E, with exactly the same
D, but without overriding any method.
init on an instance of
will be bound to a particular method implementation. If that
implementation is provided by a direct superclass of
E or is only visible through a single direct
E, than that is the superclass a
message to super in
D refers to. If, however, there
is a method clash, or the method is visible through more than one
direct superclass, the super reference is ambiguous and must be
disambiguated, as shown in this example (note that the syntax of
directing which super to message is different from `casting
Net effect is that when dynamic loading introduces an
my_counter = 1;
= [super (B) init];
init method for instances of class
that change will not be applicable to this method and its
messaging of super.
That's it for this moment. More interesting bits, such the answer to
the question `Why does TOM not have protocols, interfaces, or
signatures?' in a future highlight.