Inheritance is a basic feature of an object-oriented language.
In EIEIO, a defined class specifies the super classes from which it
inherits by using the second argument to defclass
. Here is an
example:
(defclass my-baseclass () ((slot-A :initarg :slot-A) (slot-B :initarg :slot-B)) "My Baseclass.")
To subclass from my-baseclass
, we specify it in the superclass
list:
(defclass my-subclass (my-baseclass) ((specific-slot-A :initarg specific-slot-A) ) "My subclass of my-baseclass")
Instances of my-subclass
will inherit slot-A
and
slot-B
, in addition to having specific-slot-A
from the
declaration of my-subclass
.
EIEIO also supports multiple inheritance. Suppose we define a second baseclass, perhaps an “interface” class, like this:
(defclass my-interface () ((interface-slot :initarg :interface-slot)) "An interface to special behavior." :abstract t)
The interface class defines a special interface-slot
, and also
specifies itself as abstract. Abstract classes cannot be
instantiated. It is not required to make interfaces abstract, but it
is a good programming practice.
We can now modify our definition of my-subclass
to use this
interface class, together with our original base class:
(defclass my-subclass (my-baseclass my-interface) ((specific-slot-A :initarg specific-slot-A) ) "My subclass of my-baseclass")
With this, my-subclass
also has interface-slot
.
If my-baseclass
and my-interface
had slots with the same
name, then the superclass showing up in the list first defines the
slot attributes.
Inheritance in EIEIO is more than just combining different slots. It is also important in method invocation. Methods.
If a method is called on an instance of my-subclass
, and that
method only has an implementation on my-baseclass
, or perhaps
my-interface
, then the implementation for the baseclass is
called.
If there is a method implementation for my-subclass
, and
another in my-baseclass
, the implementation for
my-subclass
can call up to the superclass as well.