Summary
- You cause a class to inherit using
ChildClassName.prototype = new ParentClass();
.
- You need to remember to reset the property for the
constructor
class using ChildClassName.prototype.constructor=ChildClassName
.
- You can call ancestor class methods which your child class have overridden using the
Function.call()
method.
- Javascript does not support protected methods.
Example
To the following is a sample showing inheritance between and classes:
functionmammal (name) { This. name=name; This. offspring=[];} Mammal.prototype.haveABaby=function(){ varnewbaby=NewMammal ("Baby" + This. Name); This. Offspring.push (Newbaby); returnNewbaby;} Mammal.prototype.toString=function(){ return' [Mammal ' + This. name+ ' "] ';} Cat.prototype=NewMammal ();//Here's where the inheritance occursCat.prototype.constructor=cat;//Otherwise instances of Cat would have a constructor of mammalfunctionCat (name) { This. name=name;} Cat.prototype.toString=function(){ return' [Cat ' + This. name+ ' "] ';} varSomeanimal =NewMammal (' Mr Biggles ');varMypet =NewCat (' Felix '); alert (' Someanimal is ' +someanimal);//results in ' someanimal is [mammal "Mr Biggles"]Alert (' Mypet is ' +mypet);//results in ' mypet is [Cat ' Felix '] 'Mypet.haveababy (); //calls a method inherited from mammalalert (myPet.offspring.length);//shows that the cat have one baby nowAlert (mypet.offspring[0]);//results in ' [Mammal ' Baby Felix '] '
The Someanimal & Mypet above inner logical struct:
Using the
.constructor
Property
Look at the last line in the above example. The baby of a cat should is a cat, right? While The haveababy ()
method worked, this method Specifically asks to create A new mammal
. While we could make a new haveababy ()
method for The cat
subclass like This.offspring.push (new cat ( "Baby" +this.name)
, it would Being better to has the ancestor class make an object of the correct type.
Every object instance in JS have a property named constructor
that points to its parent class. For Example, someanimal. Constructor==mammmal
is true. Armed with this knowledge, we can remake The haveababy ()
method like this:
mammal.prototype.haveababy=function() { var newbaby=Newthis. Constructor ("Baby" +this. Name); This . Offspring.push (Newbaby); return Newbaby;} ... mypet.haveababy (); // alert (mypet.offspring[0]); //
Calling ' Super ' methods
Let's extend the example now and that's when baby kittens is created, they ' mew ' right after being born. To does this, we want to write our own custom Cat.prototype.haveABaby()
method, which are able to call the original Mammal.prototype.haveABaby()
method:
cat.prototype.haveababy=function() { Mammal.prototype.haveABaby.call (this); Alert ("mew!" );}
The above a little bit bizarre. Javascript does not has any sort of ' super ' property, which the would point to its parent class. Instead, you use the call()
method of an Function
object, which allows you to run a function using a different object as context For it.
Making your own ' super ' property
Rather than have to know That cat
inherits from mammal< /code>, and have to type In mammal. Prototype
each time wanted to call an ancestor method, wouldn ' t it is nice to has your own propert Y of the cat pointing to its ancestor class? Those familiar with other OOP languages May is tempted to the property ' super ', but js reserves this word For the future use. The word ' parent ', while used in some DOM items, is free for the JS language itself, so let's call It parent
in this example:
New mammal (); Cat.prototype.constructor== mammal.prototype; Cat.prototype.haveABaby=function() { varthis. Parent.haveABaby.call (this); Alert ("mew!" ); return
Spoofing Pure Virtual Classes
Some OOP Languages has the concept of a pure virtual class...one which cannot be instantiated itself, and only inherited From. For example, you might has a LivingThing
class which Mammal
inherited from, and you didn ' t want someone to be able to make a without specifying what type of thing it is. Making the virtual class an object instead of a function.
The following example shows how this could is used to simulate a pure virtual ancestor:
Livingthing ={beborn:function(){ This. alive=true; } } ... Mammal.prototype=livingthing; Mammal.prototype.parent= livingthing;//note:not ' Livingthing.prototype 'mammal.prototype.haveababy=function(){ This. Parent.beBorn.call ( This); varnewbaby=New This. Constructor ("Baby" + This. Name); This. Offspring.push (Newbaby); returnNewbaby;}
With the above, doing something like var spirit = new LivingThing()
would result in an error, since are not LivingThing
a function, and hence can ' t be used as a constructor.
Convenient inheritance
Rather than writing 3 lines every time you want to inherit one class from another, it's convenient to extend the Function object to does it for you:
Function.prototype.inheritsFrom =function(parentclassorobject) {if(Parentclassorobject.constructor = =Function) { //Normal Inheritance This. prototype =NewParentclassorobject; This. Prototype.constructor = This; This. prototype.parent =Parentclassorobject.prototype; } Else { //Pure Virtual Inheritance This. prototype =Parentclassorobject; This. Prototype.constructor = This; This. prototype.parent =Parentclassorobject; } return This;} ////Livingthing ={beborn:function(){ This. Alive =true; } } ////functionmammal (name) { This. name=name; This. offspring=[];} Mammal.inheritsfrom (livingthing); Mammal.prototype.haveABaby=function(){ This. Parent.beBorn.call ( This); varNewbaby =New This. Constructor ("Baby" + This. Name); This. Offspring.push (Newbaby); returnNewbaby;} ////functionCat (name) { This. name=name;} Cat.inheritsfrom (mammal); Cat.prototype.haveABaby=function(){ varThekitten = This. Parent.haveABaby.call ( This); Alert ("Mew!"); returnThekitten;} Cat.prototype.toString=function(){ return' [Cat ' + This. name+ ' "] ';} ////varFelix =NewCat ("Felix" );varKitten = Felix.haveababy ();//mew!Alert (kitten);//[Cat "Baby Felix"]
Just Make sure-this method is immediately after your constructor and before you extend the prototype for the object.
Protected methods?
Some OOP Languages has the concept of ' protected ' methods-methods that exist in a parent or ancestor class which can only Be called by descendants of the object (on each other), and not by external objects. These is not supported in JS. If you are need such, you'll have the to write your own framework, ensuring so each class had a ' parent ' or some such property , and walking up the tree to find ancestors and checking whether or not the calling object is the same type. Doable, but not enjoyable.
Quote from:
OOP in JS, part 2:inheritance
OOP in Js-inheritance