A lot of people have trouble making inheritable objects in JavaScript, but it is really simple. Note that you won't be able to inherit Java objects in Rhino, but this works really well for raw JavaScript.
First, we need to make a new object type. We'll call it "MObject".
Code:
function MObject() {
this.inherits = [Object];
this.instanceOf = function(type) {
return (this.inherits.indexOf(type) != -1)
}
}
This will be the basis for our inheritable JavaScript objects. Next, let's make two classes. "Person" and "Student".
Code:
function Person(name) {
var obj = new MObject(); //Construct the class you are extending here
obj.inherits.push(Person); //Add the type
obj.name = name;
obj.sayHello = function() {
console.log("Hello, I am a person named " + obj.name);
};
obj.sayThis = function(what) {
console.log(obj.name + ": " + what);
};
return obj;
}
Notice that obj is returned, since we won't technically be using this function as a constructor.
Code:
function Student(name) {
var obj = new Person(name); //We are extending Person
obj.inherits.push(Student);
obj.sayHello = function() {
console.log("Hello, I am a student named " + obj.name);
};
return obj;
}
We make a new object using Person as our super constructor, then adding the Student type.
This will work for extending infinitely many objects as you always start constructing from MObject. It returns to the line to add the type to obj.inherits, which is used for instanceOf.
You can now create these objects with or without the new keyword.
Code:
student = new Student("Steve");
//OR
student = Student("Steve");
//will accomplish the same task with no difference
Code:
person = Person("Bob");
person.sayHello(); //Output: "Hello, I am a person named Bob"
student = Student("Steve");
student.sayHello(); //Output: "Hello, I am a student named Steve"
student.sayThis("Hello world!"); //Output: "Steve: Hello world!"
Next, let's look at using the instanceof keyword vs. the object method.
Code:
student = Student("Steve");
student instanceof Object => True
student instanceof MObject => True
student instanceof Person => False
student instanceof Student => False
It only recognizes student as an MObject or an Object. This is actually useful later on.
Code:
student = Student("Steve");
student.instanceOf(Object) => True
student.instanceOf(MObject) => False //You could add MObject to the inheritance list if desired
student.instanceOf(Person) => True
student.instanceOf(Student) => True
All types you added return true, as expected.
There is a problem. What if you want to test the instanceof of an object you aren't sure the type of???
Well that's why you make your own function to do just that!
Code:
function isInstanceOf(obj, type) {
if(obj instanceof MObject) {
return obj.instanceOf(type);
} else return obj instanceof type;
}
Since all objects created through MObject are always considered an instance of MObject, we can just use the instanceOf method in any object that is an instance of MObject. Otherwise, use the default instanceof keyword. If you use this, you should replace all instanceof keywords with the isInstanceOf function.
Finally, our multi-inheritance library looks like this:
Code:
function MObject() {
this.inherits = [Object];
this.instanceOf = function(type) {
return (this.inherits.indexOf(type) != -1)
}
}
function isInstanceOf(obj, type) {
if(obj instanceof MObject) {
return obj.instanceOf(type);
} else return obj instanceof type;
}
Hope this helps!