Classical Inheritance in JavaScript
?? JavaScript is a class-free, object-oriented language, and as such, it
uses prototypal inheritance instead of classical inheritance. This can be
puzzling to programmers trained in conventional object-oriented languages
like C++ and Java. JavaScript's prototypal inheritance has more expressive
power than classical inheritance, as we will see presently.
??? But first, why do we care about inheritance at all? There are
primarily two reasons. The first is type convenience. We want the language
system to automatically cast references of similar classes. Little type-
safety is obtained from a type system which requires the routine explicit
casting of object references. This is of critical importance in strongly-
typed languages, but it is irrelevant in loosely-typed languages like
JavaScript, where object references never need casting.
??? The second reason is code reuse. It is very common to have a quantity
of objects all implementing exactly the same methods. Classes make it
possible to create them all from a single set of definitions. It is also
common to have objects that are similar to some other objects, but
differing only in the addition or modification of a small number of
methods. Classical inheritance is useful for this but prototypal
inheritance is even more useful.
??? To demonstrate this, we will introduce a little sugar which will let
us write in a style that resembles a conventional classical language. We
will then show useful patterns which are not available in classical
languages. Then finally, we will explain the sugar.
Classical Inheritance
First, we will make a Parenizor class that will have set and get methods
for its value, and a toString method that will wrap the value in parens.
function Parenizor(value) {
????this.setValue(value);
}
Parenizor.method('setValue', function (value) {
????this.value = value;
????return this;
});
Parenizor.method('getValue', function () {
????return this.value;
});
Parenizor.method('toString', function () {
????return '(' + this.getValue() + ')';
});
The syntax is a little unusual, but it is easy to recognize the classical
pattern in it. The method method takes a method name and a function,
adding them to the class as a public method.
So now we can write
myParenizor = new Parenizor(0);
myString = myParenizor.toString();
As you would expect, myString is "(0)".
Now we will make another class which will inherit from Parenizor, which is
the same except that its toString method will produce "-0-" if the value
is zero or empty.