Inheritance provides a powerful means to organize
a collection of objects.
It may be used either to provide a conceptual model
of the relations between the various objects that play a role in the system,
as a mechanism to factorize code (as in the example showing how
to factor out search control) or as a method of a stepwise refinement
of object specifications. C.f. [Tom87].
\nop{
As in the example showing how to factor out control,
inheritance allows the common part of objects to
be shared by isolating it in an object from which the
shared code may be inherited.
Such a mechanism is useful in particular for representing
knowledge.
}
Static inheritance
Inheritance may occur in a number of guises.
Most simply, inheritance may be viewed as code-sharing.
For the inheriting object, extra code must be specified
such that the object in some sense specializes
the inherited object.
In a typed setting we would be tempted to speak of
the inheriting object as belonging to
a subtype of the type of the inherited object.
However, in [Am87a] it is adequately observed
that subtyping is a far more abstract notion,
that encompasses inheritance by code-sharing.
Dynamic inheritance
A rather different form of inheritance, found for instance
in Actor languages [Ag86], is achieved by delegating
messages to the inherited objects,
whenever the inheriting object does not provide
any specific functionality for dealing with a method call.
In contrast to code-sharing, inheritance by delegation is dynamic.
See also [US87].
Inheritance in DLP is static.
Objects in DLP may inherit non-logical variables
from other objects as well as clauses, by code sharing.
With respect to the clauses of an object, inheritance in DLP
must be regarded as a mechanism to extend a logical theory.
Semantically, extending a theory results in a more
precisely defined model.
Operationally, it allows to derive more goals -- namely
all the statements made true by the combined set of clauses.
In this section we will give a more precise description of the
inheritance mechanism offered by DLP.
We will discuss multiple inheritance,
what to do with name clashes,
and we will explain the difference between overriding
already defined clauses and adding clauses to allow (more) backtracking.
As an example of the use of inheritance to specialize a given object, a semaphore
will be characterized as a special kind of counter,
extending the functionality of a counter with the behavioral
characteristics of a semaphore.
Next, an example will be given illustrating how to deal
with self-reference when delegating messages to other objects.
Finally, we will give an example to illustrate how inheritance
may be used to add knowledge to an existing object by extending
the definition of a predicate.