Link to home
Start Free TrialLog in
Avatar of nmoldav
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?
Avatar of nmoldav
nmoldav

ASKER

Adjusted points to 400
Does this work?
function LibraryItem_writeInfo() {
  t = Item(price);
  t.writeInfo();
  write('Location: ' + location + "<br>\n");
}

Martin
Avatar of nmoldav

ASKER

Edited text of question
Avatar of nmoldav

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.

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.super = new Item();

And now LibraryItem.super.writeInfo 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
<html>
<script>

function Item_writeInfo()
{document.writeln('Price: ' + this.price + '<br>\n');}

function Item(price)
{this.price = price || null;
 return this;
}
Item.prototype.Item_writeInfo = 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.LibraryItem_writeInfo = LibraryItem_writeInfo;


</script>
<body>

<script>

document.writeln('CREATING:  new LibraryItem(50," bookshelf")<br>');
var vvv = new LibraryItem(50," bookshelf");

document.writeln("<h2>vvv.Item_writeInfo():</h2>");
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 :)
Avatar of nmoldav

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.

ASKER CERTIFIED SOLUTION
Avatar of kollegov
kollegov

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of nmoldav

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.price.value, this.form.location.value); a.writeInfo();">
</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.

Avatar of nmoldav

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__.price = " + 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

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.constructor(price);
      this.writeInfo = LibraryItem_writeInfo;
}
LibraryItem.prototype = new Item();

function LibraryItem_writeInfo()
{
      LibraryItem.prototype.writeInfo();
      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>