![]() |
Web Development »
Client side scripting »
General
License: The Code Project Open License (CPOL)
True inheritence with plain-old JavaScriptBy Kenneth KasajianThis article describes a technique for making use of inheritence with JavaScript, including inheriting interface, implementation and data from base classes |
Javascript, CSS, HTML, ASP, ASP.NET, Ajax
|
||||||||
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
This article describes a technique for making use of inheritence with JavaScript, including inheriting interface, implementation and data from base classes. In this example, there's a base Animal class that has a data member called lifespan. Animal has a virtual function called getSpeachText() which should return a message that a particular animal will say when it is asked to talk. The generic Animal class just says that it can't talk. Derived classes should override and return some text such as "bow wow" for dogs or "meow" for cats. The Animal class also has a non-virtual function called talk() which simply calls getSpeachText() to get the text and then displays it to the console. The lifespan field is initialized to a default value of 100. It is a public data member that any derived class can access and provide an inital value for (to change the default 100 set by the base).
The example below will illustrate these features in C++ and JavaScript.
This example creates two classes derived from Animal, called Dog and Human. Both override the getSpeachText() method. Only the Dog class changes the lifespan data member (to 15). The Human class uses the default 100 as initialized in the base class.
The technique is to use the fact that the prototype property of a user-defined class can be changed to point to an object. Therefore, if one points the prototype property of a derived class to a new instance of the base class, then the chain of responsibility will include this instance. This way a member of the base class may be accessed via an instance of the derived class if the derived class doesn't have the same member defined.
I used JScript with WSH (Windows Scripting Host), but the same stuff works with Netscape's and all other versions of JavaScript. (Note: to test with Netscape's JavaScript without the browser, obtain jsshell.exe from mozilla.org. This is a shell that executes JavaScript files. The built-in "print" statement in this shell lets you output data to 'standard out'.) If you have WSH installed on your machine, you can run the JavaScript version by placing the source in an Animal.js file and then double-clicking on it. To compile the C++ version with Visual C++ installed, use the following command to create Animal.exe.
cl Animal.cpp -GX
#include <iostream>
class Animal
{
public:
Animal()
{
lifespan = 100;
}
void talk()
{
std::cout << getSpeachText() << std::endl;
}
virtual const char* getSpeachText()
{
return "Generic Animal doesn't talk";
}
int lifespan;
};
class Dog : public Animal
{
public:
Dog()
{
lifespan = 15;
}
virtual const char* getSpeachText()
{
return "Bow wow";
}
};
class Human : public Animal
{
public:
virtual const char* getSpeachText()
{
return "Hi there";
}
};
void main()
{
Dog d;
std::cout << "Dog's lifespan: ";
std::cout << d.lifespan;
std::cout << " and talks by saying: ";
std::cout << std::endl;
d.talk();
Human h;
std::cout << "Human's lifespan: ";
std::cout << h.lifespan;
std::cout << " and talks by saying: ";
std::cout << std::endl;
h.talk();
}
function Animal_getSpeachText()
{
return "Generic Animal doesn't talk"
}
function Animal_talk()
{
WScript.Echo( this.getSpeachText() )
}
function Animal()
{
this.lifespan = 100
this.talk = Animal_talk
this.getSpeachText = Animal_getSpeachText
}
function Dog_getSpeachText()
{
return "Bow wow"
}
function Dog()
{
this.lifespan = 15
this.getSpeachText = Dog_getSpeachText
}
Dog.prototype = new Animal
function Human_getSpeachText()
{
return "Hi there"
}
function Human()
{
this.getSpeachText = Human_getSpeachText
}
Human.prototype = new Animal
function main()
{
var d = new Dog
WScript.Echo( "Dog's lifespan: " + d.lifespan + " and talks by saying:" )
d.talk()
var h = new Human
WScript.Echo( "Human's lifespan: " + h.lifespan + " and talks by saying:" )
h.talk()
}
main()
The output from both samples should look something like this:
Dog's lifespan: 15 and talks by saying:
Bow wow
Human's lifespan: 100 and talks by saying:
Hi there
You can also call the constructor of the base class from the constructor of the derived class, as in C++, by assigning the the base class constructor to some arbitrary method name of the derive class (such as "base") and then calling that method on the "this" object in the constructor of the derived class. This is necessary if you want to propage constructor arguments passed to the drived class constructor to the base class constructor. In C++, you do this by specifying the base class name in the member initialization list of the constructor of the derived class.
In the above sample, if both the Animal and Dog classes took a lifespan value as a parameter in their constructor, then the constructor for the Dog class would need to pass the argument to the constructor of its base class, the Animal class. The modified form of Dog's constructor would look like this:
class Dog : public Animal
{
public:
Dog( int lifespan )
: Animal( lifespan )
{
}
...
function Dog( lifespan )
{
this.base = Animal
this.base( lifespan )
...
}
| You must Sign In to use this message board. | |||||||||||||||
|
|||||||||||||||
|
|||||||||||||||
|
|||||||||||||||
|
|||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 9 Feb 2008 Editor: |
Copyright 2008 by Kenneth Kasajian Everything else Copyright © CodeProject, 1999-2009 Web22 | Advertise on the Code Project |