I would like to implement the following behavior in JS. Please note that the syntax is symbolic.
This is my parent class
class = TList {
FList: array;
function AddElement(Ele) {
Flist.Add(Ele)
};
function RemoveEle(Ele) {
FList.Remove(Ele)
};
}
Now I'm going to inherit from this class. My child class should automatically have all the properties of the parent and should be able to extend them without rewriting the code.
class = TAlertList(inherit from TList) {
function AddElement(Ele) {
Alert('element will be added');
call.parent.AddElement(Ele)
};
function RemoveElement(Ele) {
call.parent.RemoveElement(Ele);
Alert('element removed');
}
}
Please note how I inherit the parent methods at places I wish.
Now I should be able to create an object from my child class and do the following.
MyAlertList = new TAlertList;
MyAlertList.Add('hello');
console.log(MyAlertList.FList);
I should be able to inherit more child classes from TAlertList and be able to change the existing behavior. I need to do this in pure ES5 without using any libraries. Standard OOP practices are expected.
This is Q&A
Edit - Don't forget to read @paul's comment too if you planning to read the full text.
Almost all the answers came in were based on the popular "Person" example in the MDN documentation about JS OOP.
The theory behind this method is to put the fields of the object inside a constructor function while implementing the methods in a prototype object. A child object can inherit all the fields by calling the constructor function with a contrived
this
value. Also it can inherit all the methods by having the same prototype object of the parent as it's prototype object too. The only rule is that you need to call the methods usingcall
orapply
to point the methods to the correctthis
object when implementing inheritance.I didn't like this approach for two reasons.
The fields and methods of an objects has to be separated between two objects (fields - constructor function, methods - prototype). This doesn't have the flavor of a unique behavior of a unique entity - which should be a single class.
You have to specify the name of the parent object when inheriting. This is not automatic. Let's say object C inherits from the object A. So, inside the methods of the object C, you need to mention object A when inheriting from it. (
TList.prototype.AddElement.call(this, Ele);
) What if object B comes in between later on? You will have to change all the inheriting methods of C to call from B. This is in no way near good inheritance.I wanted to overcome these problems in MDN method. I came up with the following model with no
this
nocall
and noapply
. Code is simple and easy to follow. You don't have to mention the name of the parent object when inheriting from it. So, a new class can come in between the parent and the child at any time without too many changes. Please discuss this and point out the weaknesses of this model.Here is the function which returns the parent object.
Now comes the child object:
You can have grand children object and inherit from parent without mentioning their names. Let's say you have to put
tCustomList
betweentList
andtAlertList
. All you have to do is to tell thetAlertList
to inherit fromtCustomList
in a single place. (var ret = Object.create(tCustomList());
) Everything else remain the same.Here is the fiddle.
Please note that the
TList
constructor should be applied to theTAlertList
instance;ES5, first set up the base constructor
Next set up the constructor which extends it, see how this means calling the base constructor on the instance being created by the extended constructor and creating a prototype object which inherits the prototype of the base constructor
ES6 syntax makes use of the
super
keywordBack to ES5, generalising as a factory so you can see a sort of algorithm of how to do it
So then
Please note that this is an example of the algorithm you should be following when you write each extended constructor, not production code
Your code would be the following
This is an approximation to know how the inherit works in JavaScript.
So, the classic super call is
With pure ES5, you could do it like this:
Couple of notes:
The
FList
property of its parent will actually be shared amongst all objects that inherit from the parent unless overwritten. That means that if you don't overwriteFList
you'll get this:In my opinion, it would be best if you named your children functions with other names different from the parent. This way you don't need to do:
You can just call them like this:
Of course, it's not a static way to call the parent as you can overwrite the function with your own. Then again
TList.prototype.function
isn't necessary the function of the parent of the object that owns the function. For that you'd need to use non-standard ES5__proto__
property.Unless you plan on juggling the function around different objects, you don't need that.