nmoldav
asked on
Calling a superclass method inside an overrided method
I haven't found the syntax to call a superclass function
from inside an overrided function. For instance:
function Item(price) {
this.price = price || null;
this.writeInfo = Item_writeInfo;
return this;
}
function Item_writeInfo() {
write("Price: " + price + "<br>\n");
}
function LibraryItem(price, location) {
this.location = location;
this.price = price;
this.writeInfo = LibraryItem_writeInfo;
return this;
}
LibraryItem.prototype = new Item();
function LibraryItem_writeInfo() {
// Now here I'd like to call Item_writeInfo
// In Java it would be:
// super.writeInfo();
write('Location: ' + this.location + "<br>\n");
}
Is there any way to do this elegantly?
from inside an overrided function. For instance:
function Item(price) {
this.price = price || null;
this.writeInfo = Item_writeInfo;
return this;
}
function Item_writeInfo() {
write("Price: " + price + "<br>\n");
}
function LibraryItem(price, location) {
this.location = location;
this.price = price;
this.writeInfo = LibraryItem_writeInfo;
return this;
}
LibraryItem.prototype = new Item();
function LibraryItem_writeInfo() {
// Now here I'd like to call Item_writeInfo
// In Java it would be:
// super.writeInfo();
write('Location: ' + this.location + "<br>\n");
}
Is there any way to do this elegantly?
Does this work?
function LibraryItem_writeInfo() {
t = Item(price);
t.writeInfo();
write('Location: ' + location + "<br>\n");
}
Martin
function LibraryItem_writeInfo() {
t = Item(price);
t.writeInfo();
write('Location: ' + location + "<br>\n");
}
Martin
ASKER
Edited text of question
ASKER
Martin, your code works with some modifications, but
it's not quite elegant because you've to hardcode
the superclass name and create a new object. I've
already done something similar but I was actually
looking for a simpler solution. I've tried using
the __proto__ attribute but it didn't work:
function LibraryItem_writeInfo() {
this.__proto__.writeInfo() ;
write('Location: ' + this.location + '<br>\n');
}
Actually, it works here but the function I'm using
doesn't just read attributes but adds new ones
and if I call the 'superclass' function using __proto__
the new attributes don't end up where I want them.
it's not quite elegant because you've to hardcode
the superclass name and create a new object. I've
already done something similar but I was actually
looking for a simpler solution. I've tried using
the __proto__ attribute but it didn't work:
function LibraryItem_writeInfo() {
this.__proto__.writeInfo()
write('Location: ' + this.location + '<br>\n');
}
Actually, it works here but the function I'm using
doesn't just read attributes but adds new ones
and if I call the 'superclass' function using __proto__
the new attributes don't end up where I want them.
I'm kind of puzzled as to what you are trying to do, but I do know that you are using the prototype property incorrectly. To do something similar to what you are saying (I think), do this:
LibraryItem.prototype.supe r = new Item();
And now LibraryItem.super.writeInf o is Item_writeInfo(), but LibraryItem.writeInfo is still LibraryItem_writeInfo()
Is that what you mean?
Another problem you may be having is your use of
this.price = price || null;
.which is not supported on all platforms. You should probably write it as:
this.price = (price) ? price : null;
Hope that helps.
Cheers.
-Quixote
LibraryItem.prototype.supe
And now LibraryItem.super.writeInf
Is that what you mean?
Another problem you may be having is your use of
this.price = price || null;
.which is not supported on all platforms. You should probably write it as:
this.price = (price) ? price : null;
Hope that helps.
Cheers.
-Quixote
<html>
<script>
function Item_writeInfo()
{document.writeln('Price: ' + this.price + '<br>\n');}
function Item(price)
{this.price = price || null;
return this;
}
Item.prototype.Item_writeI nfo = Item_writeInfo;
LibraryItem.prototype=Item .prototype
function LibraryItem(price, location)
{ this.price = price;
this.location = location;
return this;
}
function LibraryItem_writeInfo()
{ this.Item_writeInfo();
document.writeln('Location : ' + this.location + "<br>\n");
}
LibraryItem.prototype.Libr aryItem_wr iteInfo = LibraryItem_writeInfo;
</script>
<body>
<script>
document.writeln('CREATING : new LibraryItem(50," bookshelf")<br>');
var vvv = new LibraryItem(50," bookshelf");
document.writeln("<h2>vvv. Item_write Info():</h 2>");
vvv.Item_writeInfo();
document.writeln("<h2> vvv.LibraryItem_writeInfo( ):</h2>");
vvv.LibraryItem_writeInfo( );
</script>
</body>
</html>
Isn't it what you was asking for?
Sorry I changed write to document.writeln
just for easy testing :)
<script>
function Item_writeInfo()
{document.writeln('Price: ' + this.price + '<br>\n');}
function Item(price)
{this.price = price || null;
return this;
}
Item.prototype.Item_writeI
LibraryItem.prototype=Item
function LibraryItem(price, location)
{ this.price = price;
this.location = location;
return this;
}
function LibraryItem_writeInfo()
{ this.Item_writeInfo();
document.writeln('Location
}
LibraryItem.prototype.Libr
</script>
<body>
<script>
document.writeln('CREATING
var vvv = new LibraryItem(50," bookshelf");
document.writeln("<h2>vvv.
vvv.Item_writeInfo();
document.writeln("<h2> vvv.LibraryItem_writeInfo(
vvv.LibraryItem_writeInfo(
</script>
</body>
</html>
Isn't it what you was asking for?
Sorry I changed write to document.writeln
just for easy testing :)
ASKER
Kollegov,
that's not exactly was I was looking for. In fact, I had
done something similar and then I posted the question to
see if there was a more elegant way around. I don't like
this approach because inside LibraryItem_writeInfo()
you call this.Item_writeInfo. The fact I don't like is that
you've already defined that LibraryItem inherits from Item
so there should be a way of calling its superclass method without
having to write the complete name.
In other words, I was looking for something along the lines of:
super() or this.super() or this.super.writeInfo()
instead of this.Item_writeInfo()
After posting the question I tried this.__proto__.writeInfo()
but I had a few problems.
that's not exactly was I was looking for. In fact, I had
done something similar and then I posted the question to
see if there was a more elegant way around. I don't like
this approach because inside LibraryItem_writeInfo()
you call this.Item_writeInfo. The fact I don't like is that
you've already defined that LibraryItem inherits from Item
so there should be a way of calling its superclass method without
having to write the complete name.
In other words, I was looking for something along the lines of:
super() or this.super() or this.super.writeInfo()
instead of this.Item_writeInfo()
After posting the question I tried this.__proto__.writeInfo()
but I had a few problems.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I've reread your comment and the document on Object Hierarchy
and Inheritance in JavaScript and it seems I was taking a
different approach. I understand now why you can't override
methods without loosing the original ones. However, the way
I was creating the objects it is possible to do so. Please
take a look at the following code. Perhaps you might argue
it's not real inheritance.
<html>
<script Language="JavaScript1.2">
function Item(price) {
this.price = price || 0;
this.writeInfo = Item_writeInfo;
}
function Item_writeInfo() {
alert("My price is " + this.price);
}
function LibraryItem(price, location) {
this.__proto__.price = price;
this.location = location;
this.writeInfo = LibraryItem_writeInfo;
}
LibraryItem.prototype = new Item;
function LibraryItem_writeInfo() {
// Call the 'superclass' overrided method
this.__proto__.writeInfo() ;
alert("My location is " + this.location);
}
</script>
<body>
<form>
Price: <input type=text name=price><br>
Location: <input type=text name=location><br>
<input type=button value="run" onClick="JavaScript: var a = new LibraryItem(this.form.pric e.value, this.form.location.value); a.writeInfo();">
</form>
</body>
</html>
and Inheritance in JavaScript and it seems I was taking a
different approach. I understand now why you can't override
methods without loosing the original ones. However, the way
I was creating the objects it is possible to do so. Please
take a look at the following code. Perhaps you might argue
it's not real inheritance.
<html>
<script Language="JavaScript1.2">
function Item(price) {
this.price = price || 0;
this.writeInfo = Item_writeInfo;
}
function Item_writeInfo() {
alert("My price is " + this.price);
}
function LibraryItem(price, location) {
this.__proto__.price = price;
this.location = location;
this.writeInfo = LibraryItem_writeInfo;
}
LibraryItem.prototype = new Item;
function LibraryItem_writeInfo() {
// Call the 'superclass' overrided method
this.__proto__.writeInfo()
alert("My location is " + this.location);
}
</script>
<body>
<form>
Price: <input type=text name=price><br>
Location: <input type=text name=location><br>
<input type=button value="run" onClick="JavaScript: var a = new LibraryItem(this.form.pric
</form>
</body>
</html>
Actually what do this line :?)
LibraryItem.prototype = new Item;
If you read definitions of prototype property and think about it
you will find that it's equivalent to:
function LibraryItem(price, location)
{ //inherit manually what you need to inherit
this.mysuper = new Item(price)
//... so on...
}
The difference is that in my case I create 'mysuper' property.
and in first way this property is predefined '__proto__'
Hmmmm....
BTW I was very surprized, the "Object Hierarchy and Inheritance in JavaScript" document is only place where __proto__ mentioned.
When I greped through the JavaScript references I didn't find it
documented :) Should be I guess :)
As I never read this article before I just invented equivalent
for this undocumented (in references) property.
(Just curious how many times I invented bycicles in my life,
Each day here, learn something new :)
Thanks, your question was very interesting ...
As for your actual code problems, I think the problem
is in some other minor bug.
LibraryItem.prototype = new Item;
If you read definitions of prototype property and think about it
you will find that it's equivalent to:
function LibraryItem(price, location)
{ //inherit manually what you need to inherit
this.mysuper = new Item(price)
//... so on...
}
The difference is that in my case I create 'mysuper' property.
and in first way this property is predefined '__proto__'
Hmmmm....
BTW I was very surprized, the "Object Hierarchy and Inheritance in JavaScript" document is only place where __proto__ mentioned.
When I greped through the JavaScript references I didn't find it
documented :) Should be I guess :)
As I never read this article before I just invented equivalent
for this undocumented (in references) property.
(Just curious how many times I invented bycicles in my life,
Each day here, learn something new :)
Thanks, your question was very interesting ...
As for your actual code problems, I think the problem
is in some other minor bug.
ASKER
It's funny. I had read the Object Hierarchy article
before starting this project but I did not notice that
you were supossed to call the 'superclass constructor'
inside the subclass constructor. I.e:
function LibraryItem(price, location)
{ //inherit manually what you need to inherit
this.mysuper = new Item(price)
//... so on...
}
I created several objects without ever calling
this.mysuper = new Item(price), but just using
LibraryItem.prototype = new Item;
There's a difference in these two methods. The way
I did it, whenever you attempt to read or reference
an attribute, for instance, this.price, JavaScript
will try to find the attribute in the current object (this).
If it doesn't find it, it will look in this.__proto__,
this.__proto__.__proto__ and so on.. This is good.
However, when you try to *set* an attribute it will
set it on this, without checking if it already exists
in this.__proto__. So, if you have
this.__proto__.price = 1;
alert("this.price = " + this.price); // Will print 1
this.price = 2 // This will set this.price, not
// change this.__proto__.price
alert("this.price = " + this.price); // Will print 2
alert("this.__proto__.pric e = " + this.__proto__.price);
// will print 1
So there are two price attributes. This is bad. It
should check all the hierarchy to see if an attribute
exists before creating a new attribute on this.
Why does this matters? Because if you call a
method on this.__proto__, the method will only be
able to read properties defined on this.__proto__
and won't be able to access the ones defined on this.
That is to say, if inside the LibraryItem constructor
I had set
this.price = price
instead of
this.__proto__.price = price
then this.__proto__.writeInfo() would have always
printed 0, no matter what the this.price attribute's
value was.
So I guess this could be defined as 'read-only
attribute inheritance'. ;-)
My code didn't work because I was
setting the attributes on this instead of
on this.__proto__. I posted the question after
doing some sort of manual inheritance and realizing
it wasn't very elegant.
Anyway, so much for this. Thanks for your
help.
Nicolas
before starting this project but I did not notice that
you were supossed to call the 'superclass constructor'
inside the subclass constructor. I.e:
function LibraryItem(price, location)
{ //inherit manually what you need to inherit
this.mysuper = new Item(price)
//... so on...
}
I created several objects without ever calling
this.mysuper = new Item(price), but just using
LibraryItem.prototype = new Item;
There's a difference in these two methods. The way
I did it, whenever you attempt to read or reference
an attribute, for instance, this.price, JavaScript
will try to find the attribute in the current object (this).
If it doesn't find it, it will look in this.__proto__,
this.__proto__.__proto__ and so on.. This is good.
However, when you try to *set* an attribute it will
set it on this, without checking if it already exists
in this.__proto__. So, if you have
this.__proto__.price = 1;
alert("this.price = " + this.price); // Will print 1
this.price = 2 // This will set this.price, not
// change this.__proto__.price
alert("this.price = " + this.price); // Will print 2
alert("this.__proto__.pric
// will print 1
So there are two price attributes. This is bad. It
should check all the hierarchy to see if an attribute
exists before creating a new attribute on this.
Why does this matters? Because if you call a
method on this.__proto__, the method will only be
able to read properties defined on this.__proto__
and won't be able to access the ones defined on this.
That is to say, if inside the LibraryItem constructor
I had set
this.price = price
instead of
this.__proto__.price = price
then this.__proto__.writeInfo()
printed 0, no matter what the this.price attribute's
value was.
So I guess this could be defined as 'read-only
attribute inheritance'. ;-)
My code didn't work because I was
setting the attributes on this instead of
on this.__proto__. I posted the question after
doing some sort of manual inheritance and realizing
it wasn't very elegant.
Anyway, so much for this. Thanks for your
help.
Nicolas
The following program may be the answer:
(I am working in Win98 with IE 5.5)
<SCRIPT LANGUAGE=javascript>
function Item(price)
{
this.price = price;
this.writeInfo = Item_writeInfo;
}
function Item_writeInfo()
{
document.write("Price: " + this.price + "<br>");
}
function LibraryItem(price, location)
{
this.location = location;
LibraryItem.prototype.cons tructor(pr ice);
this.writeInfo = LibraryItem_writeInfo;
}
LibraryItem.prototype = new Item();
function LibraryItem_writeInfo()
{
LibraryItem.prototype.writ eInfo();
document.write('Location: ' + this.location + "<br>");
}
var test=new LibraryItem(20,"Taipei");
test.writeInfo();
</SCRIPT>
The output of this program:
Price: 20
Location: Taipei
(I am working in Win98 with IE 5.5)
<SCRIPT LANGUAGE=javascript>
function Item(price)
{
this.price = price;
this.writeInfo = Item_writeInfo;
}
function Item_writeInfo()
{
document.write("Price: " + this.price + "<br>");
}
function LibraryItem(price, location)
{
this.location = location;
LibraryItem.prototype.cons
this.writeInfo = LibraryItem_writeInfo;
}
LibraryItem.prototype = new Item();
function LibraryItem_writeInfo()
{
LibraryItem.prototype.writ
document.write('Location: ' + this.location + "<br>");
}
var test=new LibraryItem(20,"Taipei");
test.writeInfo();
</SCRIPT>
The output of this program:
Price: 20
Location: Taipei
I just found a simple way to accomplish:
<SCRIPT LANGUAGE=javascript>
function Item(price)
{
this.price = price;
this.writeInfo = Item_writeInfo;
}
function Item_writeInfo()
{
document.write("Price: " + this.price + "<br>");
}
function LibraryItem(price, location)
{
this.location = location;
Item.prototype.constructor (price);
this.writeInfo = LibraryItem_writeInfo;
}
function LibraryItem_writeInfo()
{
Item.prototype.writeInfo() ;
document.write('Location: ' + this.location + "<br>");
}
var test=new LibraryItem(20,"Taipei");
test.writeInfo();
</SCRIPT>
<SCRIPT LANGUAGE=javascript>
function Item(price)
{
this.price = price;
this.writeInfo = Item_writeInfo;
}
function Item_writeInfo()
{
document.write("Price: " + this.price + "<br>");
}
function LibraryItem(price, location)
{
this.location = location;
Item.prototype.constructor
this.writeInfo = LibraryItem_writeInfo;
}
function LibraryItem_writeInfo()
{
Item.prototype.writeInfo()
document.write('Location: ' + this.location + "<br>");
}
var test=new LibraryItem(20,"Taipei");
test.writeInfo();
</SCRIPT>
ASKER