170 5 Object-Oriented Programming Languages
These programming languages allow one subclass A to inherit from multiple par-
ent classes B
1
,...,B
k
simultaneously. Providing a meaningful semantics for multi-
ple inheritance is already a challenging problem. The difficulties of formalizing the
complex semantics of the version of multiple inheritance as provided by C++ are
discussed in [WNST06]. A fundamental problem of multiple inheritance is how to
resolve ambiguities arising from inheritance: different methods with the same name
may be inherited, or the same parent class may contribute to a subclass A along
different paths.
A trivial form of multiple inheritance is supported by the programming language
J
AVA.JAVA does not provide multiple inheritance in the strict sense: besides inher-
iting from a parent class B, a class A may only implement an arbitrary number of
interfaces. An interface is an abstract class without its own attributes. Definitions
for the methods of an interface need to be provided by its implementing subclasses.
In J
AVA jargon, the methods of an interface are abstract, in C++ jargon, pure virtual.
As interfaces do not have attributes, and as in the class A there is at most one
implementation available for each method, no ambiguities can arise. There is just
one complication. Assume that a method call e. f
(...) should be compiled, where
the statically known type of the expression e is an interface I. In general, it cannot
be guaranteed that the method f has the same relative address in all classes A
that
implement the interface I. One solution is to provide for each class A a hash table
h
A
that assigns to each name f of a method the code address of the corresponding
implementation in A. In order to allow for an efficient implementation of such hash
tables, J
AVA provides the String Pool where all statically known strings, in particular
all method names, are stored. Instead of the textual representation of the names, the
references to the representatives in the String Pool can, therefore, be used as keys.
An alternative implementation, more in line with the philosophy of C++, would
accommodate in an A-Object for each of the implemented interfaces I
j
, a reference
to a suitable method table t
A,I
j
for I
j
within the class A . The table t
A,I
j
contains the
references to the implementations of the methods declared in I
j
. Each method f of
the interface I
j
receives a fixed relative address with which the actual start address of
an implementation of f can be looked up in all tables t
A
,I
j
for implementing classes
A
.
Let us assume that an expression e has the static type I
∗ for an interface I and
evaluates at run-time to a pointer to an object o of a class A that implements I.The
method f of a call e
→ f then must be looked up in the corresponding table t
A,I
of
the object o. To find this table quickly, we let the pointer to the object o not point to
the start of the memory block of o, but to the reference to the table t
A,I
(Fig. 5.5).
This pointer represents the I-view to the object o. This idea incurs two problems.
• The methods declared in an interface may want to access the attributes of the
object. Therefore, the table for each interface I must also contain the distance
between the beginning of the object and the reference to the table t
A,I
.This
allows us to pass the recovered object reference to each call of a method f .