Classical Inheritance in JavaScript

Source: Internet
Author: User

JavaScript isClass-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 versions like C ++ and Java. javaScript's prototypal inheritance has more expressive power than classical inheritance, as we will see presently.

Java JavaScript
Stronugly-typed Loosely-typed
Static Dynamic
Classical Prototypal
Classes Functions
Constructors Functions
Methods Functions

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 automaticallyCastReferences 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 stronugly-typed versions, but it is irrelevant in loosely-typed versions 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 ages. then finally, we will explain the sugar.

Classical Inheritance

First, we will makeParenizorClass that will have set and get methods for itsValue, AndTostringMethod that will wrapValueIn 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.MethodMethod 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 woshould have CT,MystringIs"(0 )".

Now we will make another class which will inherit fromParenizor, Which is the same parameter t that itsTostringMethod will produce"-0 -"IfValueIs zero or empty.

function ZParenizor(value) {    this.setValue(value);}ZParenizor.inherits(Parenizor);ZParenizor.method('toString', function () {    if (this.getValue()) {        return this.uber('toString');    }    return "-0-";});

TheInheritsMethod is similar to Java'sExtends.UberMethod is similar to Java'sSuper. It lets a method call a method of the parent class. (The names have been changed to avoid reserved word restrictions .)

So now we can write

myZParenizor = new ZParenizor(0);myString = myZParenizor.toString();

This time,MystringIs"-0 -".

JavaScript does not have classes, but we can program as though it does.

Multiple Inheritance

By manipulating a function'sPrototypeObject, we can implement multiple inheritance, allowing us to make a class built from the methods of multiple classes. promiscuous multiple inheritance can be difficult to implement and can potentially suffer from method name collisions. we cocould implement promiscuous multiple inheritance in JavaScript, but for this example we will use a more disciplined form calledSwiss inheritance.

Suppose there isNumbervalueClass that hasSetValueMethod that checks thatValueIs a number in a certain range, throwing an exception if necessary. We only want itsSetValueAndSetRangeMethods for ourZParenizor. We certainly don't want itsToStringMethod. So, we write

ZParenizor.swiss(NumberValue, 'setValue', 'setRange');

This adds only the requested methods to our class.

Parasitic Inheritance

There is another way to writeZParenizor. Instead of inheriting fromParenizor, We write a constructor that calltheParenizorConstructor, passing off the result as its own. And instead of adding public methods, the constructor adds privileged methods.

function ZParenizor2(value) {    var that = new Parenizor(value);    that.toString = function () {        if (this.getValue()) {            return this.uber('toString');        }        return "-0-"    };    return that;}

Classical inheritance is aboutIs-Relationship, and parasitic inheritance is aboutWas-a-but-now's-Relationship. The constructor has a larger role in the construction of the object. Notice thatUberN'eSuperMethod is still available to the privileged methods.

Class Augmentation

Javascript's dynamism allows us to add or replace methods of an existing class. We can callMethodMethod at any time, and all present and future instances of the class will have that method. We can literally extend a class at any time. Inheritance works cannot actively. We call thisClass AugmentationTo avoid confusion with Java'sExtends, Which means something else.

Object Augmentation

In the static object-oriented versions, if you want an object which is slightly different than another object, you need to define a new class. in JavaScript, you can add methods to individual objects without the need for additional classes. this has enormous power because you can write far fewer classes and the classes you do write can be much simpler. recall that JavaScript objects are like HashTables. you can add new values at any time. if the value is a function, then it becomes a method.

So in the example above, I didn't needZParenizorClass at all. I cocould have simply modified my instance.

myParenizor = new Parenizor(0);myParenizor.toString = function () {    if (this.getValue()) {        return this.uber('toString');    }    return "-0-";};myString = myParenizor.toString();

We addedToStringMethod to ourMyParenizorInstance without using any form of inheritance. We can evolve individual instances because the language is class-free.

Sugar

To make the examples abve work, I wrote four sugar methods. First,MethodMethod, which adds an instance method to a class.

Function.prototype.method = function (name, func) {    this.prototype[name] = func;    return this;};

This adds a public method toFunction. prototype, So all functions get it by Class Augmentation. It takes a name and a function, and adds them to a function'sPrototypeObject.

It returnsThis. When I write a method that doesn't need to return a value, I usually have it returnThis. It allows for a cascade-style of programming.

Next comesInheritsMethod, which indicates that one class inherits from another. It shoshould be called after both classes are defined, but before the inheriting class's methods are added.

Function.method('inherits', function (parent) {    var d = {}, p = (this.prototype = new parent());    this.method('uber', function uber(name) {        if (!(name in d)) {            d[name] = 0;        }                var f, r, t = d[name], v = parent.prototype;        if (t) {            while (t) {                v = v.constructor.prototype;                t -= 1;            }            f = v[name];        } else {            f = p[name];            if (f == this[name]) {                f = v[name];            }        }        d[name] += 1;        r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));        d[name] -= 1;        return r;    });    return this;});

Again, we augmentFunction. We make an instance ofParentClass and use it as the newPrototype. We also correctConstructorField, and we addUberMethod toPrototypeAs well.

TheUberMethod looks for the named method in its ownPrototype. This is the function to invoke in the case of Parasitic Inheritance or Object Augmentation. If we are doing Classical Inheritance, then we need to find the function inParent'SPrototype.ReturnStatement uses the function'sApplyMethod to invoke the function, explicitly settingThisAnd passing an array of parameters. The parameters (if any) are obtained fromArgumentsArray. Unfortunately,ArgumentsArray is not a true array, so we have to useApplyAgain to invoke the ArraySliceMethod.

Finally,SwissMethod.

Function.method('swiss', function (parent) {    for (var i = 1; i < arguments.length; i += 1) {        var name = arguments[i];        this.prototype[name] = parent.prototype[name];    }    return this;});

TheSwissMethod loops throughArguments. For eachName, It copies a member fromParent'SPrototypeTo the new class'sPrototype.

Conclusion

Javascript can be used like a classical language, but it also has a level of Expressiveness which is quite unique. we have looked at classical inheritance, Swiss inheritance, parasitic inheritance, class augmentation, and object augmentation. this large set of code reuse patterns comes from a language which is considered smaller and simpler than Java.

Classical objects are hard. the only way to add a new member to a hard object is to create a new class. in JavaScript, objects are soft. A new member can be added to a soft object by simple assignment.

Because objects in JavaScript are so flexible, you will want to think differently about class hierarchies. Deep hierarchies are inappropriate. Shallow hierarchies are efficient and expressive.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.