I have the following code:
function Rune(){
this.subSpells = [];
}
function Modifier(){
this.type = "modifier";
}
Modifier.prototype = new Rune();
function RuneFactory(effect, inheritsFrom, initialValue){
var toReturn = function(){};
toReturn.prototype = new inheritsFrom();
toReturn.prototype.subSpells[effect] = initialValue;
return toReturn;
}
Duration = RuneFactory("duration", Modifier, 1);
Quicken = RuneFactory("quicken", Modifier, 1);
x = new Duration();
y = new Quicken();
Both x.subSpells.duration and x.subSpells.quicken equal 1. Same with y. I want x.subSpells.quicken and y.subSpells.duration to be undefined.
If I do the following for the Duration and Quicken definitions, I get the behaviour I want.
Duration = RuneFactory("duration", Rune, 1);
Quicken = RuneFactory("quicken", Rune, 1);
I think there is a problem with double inheritance. Can anyone tell me how to change my RuneFactory code such that it works with double inheritance and/or explain what's breaking? If at all possible, I would like to avoid using a framework.
Thank you!
Add following line in the Modifier function Rune.apply(this, arguments);
, since subSpells
defined at prototype level, all instance of Rune refer to same object.
And, change type of subSpells
from array to object.
As mentioned by wared would be better if you use Parasitic Combination Inheritance Pattern.
"I think there is a problem with double inheritance" - No!
At first, there's no such thing as double inheritance, you have same problem as with Modifier constructor, your instances refer to same subSpells
object (Array in your case. read about Primitive value vs Reference value or References and Values it's about .NET, but basic principles are the same in programming).
Look at How does JavaScript .prototype work?
Look at jsFiddle
function inheritPrototype(subType, superType) {
var prototype = Object.create(superType.prototype, {
constructor: {
value: subType,
enumerable: true
}
});
subType.prototype = prototype;
}
function Rune() {
this.subSpells = {};
}
function Modifier() {
Rune.apply(this, arguments);
this.type = "modifier";
}
inheritPrototype(Modifier, Rune);
function RuneFactory(effect, inheritsFrom, initialValue) {
function toReturn() {
inheritsFrom.apply(this, arguments); // you should bind this
this.subSpells[effect] = initialValue;
}
inheritPrototype(toReturn, inheritsFrom);
return toReturn;
}
Duration = RuneFactory("duration", Modifier, 1);
Quicken = RuneFactory("quicken", Modifier, 1);
x = new Duration();
y = new Quicken();
console.log(x.subSpells.duration); // 1
console.log(x.subSpells.quicken); // undefined
console.log(y.subSpells.duration); // undefined
console.log(y.subSpells.quicken); // 1
The correct way to inherit in JavaScript is:
function Parent(arg1, arg2) {
// Do something
}
function Child(arg1, arg2) {
Parent.call(this, arg1, arg2); // or Parent.apply(this, arguments)
}
Child.prototype = Object.create(Parent.prototype, {
constructor: {
value: Child
}
});
So you will need something like this:
function Rune(){
this.subSpells = {};
}
function Modifier(){
Rune.apply(this, arguments);
this.type = "modifier";
}
Modifier.prototype = Object.create(Rune.prototype, {
constructor: {
value: Modifier
}
});
function RuneFactory(effect, inheritsFrom, initialValue){
var toReturn = function(){};
toReturn.prototype = Object.create(inheritsFrom.prototype, {
constructor: {
value: Modifier
}
});
toReturn.prototype.subSpells = {};
toReturn.prototype.subSpells[effect] = initialValue;
return toReturn;
}
Duration = RuneFactory("duration", Modifier, 1);
Quicken = RuneFactory("quicken", Modifier, 1);
x = new Duration();
y = new Quicken();
NOTE: in your question .subSpells
is an array but you assign an member as it would be an object!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With