this problem. A class (
Car
) can inherit from only one parent (
Vehicle
), but it can
have multiple interfaces (
Insurable
,
Container
, etc.).
JavaScript is an interesting hybrid. It is technically a single inheritance language
because the prototype chain does not look for multiple parents, but it does provide
ways that are sometimes superior to either multiple inheritance or interfaces (and
sometimes inferior).
The primary mechanism for the problem of multiple inheritance is the concept of the
mixin. A mixin refers to functionality that’s “mixed in” as needed. Because JavaScript
is an untyped, extremely permissive language, you can mix in almost any functional‐
ity to any object at any time.
Let’s create an “insurable” mixin that we could apply to cars. We’ll keep this simple. In
addition to the insurable mixin, we’ll create a class called
InsurancePolicy
. An
insurable mixin needs the methods
addInsurancePolicy
,
getInsurancePolicy
, and
(for convenience)
isInsured
. Let’s see how that would work:
class
InsurancePolicy
() {}
function
makeInsurable
(
o
) {
o
.
addInsurancePolicy
=
function
(
p
) {
this
.
insurancePolicy
=
p
; }
o
.
getInsurancePolicy
=
function
() {
return
this
.
insurancePolicy
; }
o
.
isInsured
=
function
() {
return
!!
this
.
insurancePolicy
; }
}
Now we can make any object insurable. So with
Car
, what are we going to make
insurable? Your first thought might be this:
makeInsurable
(
Car
);
But you’d be in for a rude surprise:
const
car1
=
new
Car
();
car1
.
addInsurancePolicy
(
new
InsurancePolicy
());
// error
If you’re thinking “of course;
addInsurancePolicy
isn’t in the prototype chain,” go to
the head of the class. It does no good to make
Car
insurable. It also doesn’t make
sense: the abstract concept of a car isn’t insurable, but specific cars are. So our next
take might be this:
const
car1
=
new
Car
();
makeInsurable
(
car1
);
car1
.
addInsurancePolicy
(
new
InsurancePolicy
());
// works
This works, but now we have to remember to call
makeInsurable
on every car we
make. We could add this call in the
Car
constructor, but now we’re duplicating this
functionality for every car created. Fortunately, the solution is easy:
makeInsurable
(
Car
.
prototype
);
const
car1
=
new
Car
();
car1
.
addInsurancePolicy
(
new
InsurancePolicy
());
// works
160 | Chapter 9: Objects and Object-Oriented Programming