Vincent van Beveren <vi*****@provident.remove.this.nl> writes:
Thanks, I looked through the code, but looking through the code I come
to the conclusion that there is no way to overwrite methods in JS.
Interesting conclusion.
The trick they use for the toString method is the following:
function Parent() {
this.parentToString = function()
return "parent";
}
Define function, assign it to current object's parentToString property ...
this.toString = this.parentToString;
.... and assign same function to the toString property.
}
function Child() {
this.base = Parent;
this.base();
These two lines is and idiom for using the Parent function to initialize
the CHild object being created. It doesn't create a Parent object, and
it uses the new object, this, as the "this" for the Parent function.
this.childToString = function() {
return this.parentToString()+" and child";
So this works, because "this" has a parentToString method.
But thats a work-around. It would save a lot of trouble if there was
a simpleler way of using inherience:
There is:
---
function Parent(){};
Parent.prototype.toString = function() { return "parent"; };
function Child(){};
Child.prototype.toString = function() {
return Parent.prototype.toString() + " and child";
};
---
function Parent() {
this.foo = "bar";
this.toString = function() {
return "parent";
}
}
function Child() {
this.base = new Parent();
So here you create a new Parent *object*. You create one for each
Child object. You can reference it, but it's just part of the Child
object.
this.toString = function() {
return this.base.toString()+" and child";
}
}
c = new Child();
alert(c.foo);
alert(c.toString());
The first alert would give "bar", the second "parent and child"
No, the first alert should give "udefined", because the Child object
doesn't have a "foo" property. It has a "base" property, which is a
Parent and which therefore has a "foo" property, but the Child object
doesn't have a "foo" property itself.
could anyone tell me why this is impossible in JavaScript?
No, because it is.
Or why this hasn't been done yet?
It has.
Ok, Javascript doesn't have *class* inheritance, mainly because it doesn't
have classes.
A Javascript constructor is just a function. When creating a new object
with the "new" operator on a constructor function "Foo", you
1: create a new object,
2: make its prototype link point to the object Foo.prototype,
3: execute Foo with "this" referring to the new object, and
4: if Foo returns an object, the new operator evalutes to that, otherwise \
it evaluates to the newly constructed object.
That is, inheritance in Javascript is between objects (the prototype
objects), not classes (which doesn't exist) or functions (which merely
acts as initializers and holders of the prototype object).
Example:
---
function Foo(){};
Foo.prototype.baz = "foo";
function Bar(){};
Bar.prototype.baz = "bar";
var foo = new Foo();
var bar = new Bar();
alert(foo.baz); // foo
alert(bar.baz); // bar
Foo.prototype.baz = "arglebargle";
alert(foo.baz); // "arglebargle" - dynamic inheritance
alert(foo instanceof Foo); // true
alert(foo instanceof Bar); // false
alert(bar instanceof Foo); // false
alert(bar instanceof Bar); // true
// swap prototype
var tmp = Foo.prototype;
Foo.prototype = Bar.prototype;
Bar.prototype = tmp;
// and the surprice
alert(foo instanceof Foo); // false
alert(foo instanceof Bar); // true - because Bar.prototype is foo's proto
alert(bar instanceof Foo); // true
alert(bar instanceof Bar); // false
alert(foo.baz); // arglebargle
alert(bar.baz); // bar
---
As the "surprice" shows, the inheritance/instanceof relation follows
only the prototype object of the constructor function, not the function
itself. The function merely holds the prototype, and when a new object
is created, the function is called to initialize the object.
So, there is no class based inhertance. So, what is it that you are
trying to achieve, exactly? Because we can emulate most of it, we just
need to know which part is needed. Douglas Crockford has a page on
how to emulate different kinds of inheritance in javascript
:
<URL:http://www.crockford.com/javascript/inheritance.html>
What you seem to want is to call the Parent constructor to initialize
the Child object as well as do the initialization of the Child.
You also want to refer to the Parent object's functions when the
Child overrides them.
For that, you can just do:
---
function Parent() {...}
Parent.prototype.xxx = ...;
function Child() {
// call Parent initialization
this.parentConstructor = Parent;
this.parentConstructor();
delete this.parentConstructor;
// remember parent version
this.parentToString = this.toString();
// use it
this.toString = function() {
this.parentToString() + " and child";
}
}
---
However, that doesn't inherit the properties on the Parent.prototype
object.
The way I do that is:
---
function inheritObject(object) {
function Dummy(){};
Dummy.prototype = object;
return new Dummy();
}
function Child() {
Parent.call(this); // simpler than assigning it, calling it, and
// removing it again, but only works in modern browsers
// child initalization;
}
Child.prototype = inheritObject(Parent.prototype);
---
Example:
---
function Parent(i) { this.i = i; }
Parent.prototype.toString = function() { return "parent["+this.i+"]"; };
Parent.prototype.incI = function () { this.i++; };
function Child(i, j) {
Parent.call(this, i);
this.parentToString = Parent.prototype.toString;
this.j = j;
}
Child.prototype = inheritObject(Parent.prototype);
Child.prototype.incJ = function () { this.j++; };
Child.prototype.toString = function() {
return this.parentToString() + " and child[" + this.j + "]";
};
---
Now test this:
---
var p = new Parent(42);
var c = new Child(37,87);
alert(p.toString()); // parent[42]
alert(c.toString()); // parent[37] and child[87]
p.incI();
alert(p.toString()); // parent[43]
alert(c.toString()); // parent[37] and child[87]
c.incI();
alert(p.toString()); // parent[43]
alert(c.toString()); // parent[38] and child[87]
c.incJ();
alert(c.toString()); // parent[38] and child[88]
alert(p.incJ); // undefined
---
That is, the child has inherited the "incI" method, and the toString
method has been assimilated :)
/L
--
Lasse Reichstein Nielsen -
lr*@hotpop.com
DHTML Death Colors: <URL:http://www.infimum.dk/HTML/rasterTriangleDOM.html>
'Faith without judgement merely degrades the spirit divine.'