6
\$\begingroup\$

I have written some example code to test object inheritance, but I'm not sure if it's really the best way for an object to inherit another's functions (like Java's extends).

function Class() {
    console.log("Created class"); // The base class
}

Class.prototype.test = function() {
    console.log("Testing class"); // Add an un-overridden method, to test inheritance
};

Class.prototype.overrideMe = function() {
    console.log("Not overridden"); // Add a method to override
};

function SubClass() {
    console.log("Created subclass"); // This object will 'extend' Class.
}

// SubClass.prototype = new Class(); also works here, but the constructor is called
SubClass.prototype = Object.create(Class.prototype); // Copy the prototype

SubClass.prototype.overrideMe = function() {
    console.log("Overridden"); // Override the method
};

/* Testing */

var sub = new SubClass();

sub.test(); // Prints out "Testing class"
sub.overrideMe(); // Prints out "Overridden"

if (sub instanceof Class) {
    console.log("SubClass is an instance of Class");
} else {
    console.log("SubClass is not an instance of Class");
}

Are there any better ways to do this?

\$\endgroup\$
  • \$\begingroup\$ Not to take away from the question at hand, but more of an aside: MooTools (Wikipedia Entry) facilitates OOP javascript \$\endgroup\$ – Origineil Nov 20 '13 at 21:07
5
\$\begingroup\$

Using Class.extend

By including John Resig's code snippet to enable Class-ical inheritance, you could write this as follows :

var ExampleBaseClass = Class.extend({
    init : function() {
        console.log("Created class");
    },
    test : function() {
        console.log("Testing class"); // Add an un-overridden method, to test     inheritance        
    },
    overrideMe : function() {
        console.log("Not overridden"); // Add a method to override
    }
});

var ExampleSubClass = ExampleBaseClass.extend({
    overrideMe : function() {
        console.log("Overridden"); // Override the method
    }
});

JS Fiddle here http://jsfiddle.net/z4Z7J/, I've put the full code for the implementation of the generic Class function there, so scroll down to see how you'd use it. Normally that would just be included as a seperate JS file.

Its super neat, and handy because it takes all the prototype calls out and hides them nicely. Passing in the object literal to the extend method also allows us to group the definition of the class nicely so this appeals to folks from a classical OO background.

It goes through some fairly involved work to make instanceof work (by ensuring prototype chain is correctly maintained), does some slicing and dicing of the object literals and remapping of the this context. (Take a look at Some Useful References below this answer).

If you don't care about instanceof you free yourself up a bit and can use alternate patterns, but for the quickest hit to get the extend functionality, my vote is with John Resig's snippet.

Some Useful References

There are a number of code libraries and snippets that you can use as the basis for implementing a Class-ical type of inheritance pattern in JavaScript. For example the already mentioned John Resig's Class implementation or Dean Edwards' Base.

They're really worth taking a look at and reading through. Another interesting perspective is Douglas Crockford's Classical inheritance in JavaScript.

Especially the part at the end where he says :

I have been writing JavaScript for 8 years now, and I have never once found need to use an uber function. The super idea is fairly important in the classical pattern, but it appears to be unnecessary in the prototypal and functional patterns. I now see my early attempts to support the classical model in JavaScript as a mistake. ~ Douglas Crockford

So theres a lot to weigh up and a lot of it is highly subjective!

\$\endgroup\$
4
\$\begingroup\$

I'm sorry, I just can't resist...

if (sub instanceof Class) {
    console.log("SubClass is an instance of Class");
} else {
    console.log("SubClass is not an instance of Class");
}

Can be written as

console.log("SubClass is " + ((sub instanceof Class) ? "" : "not ") + "an instance of Class");

(Whether this is cleaner or not is subjective of course) Whether this suggestion is actually useful is doubtful.

But that's not the big point that I want to make here. When working with polymorphism, you should avoid using the instanceof operator to check which class one of your Objects is. If you find yourself doing things like "if a instanceof SomeClass then do something, otherwise do something else", then instead create a common dosomething method for the both classes and call that. Then there's no need to check which instanceof an object is. The object itself knows what to do. (Although the links are mainly about Java, if you want to do it the OOP way in JavaScript, the same principles still applies)

\$\endgroup\$
  • 1
    \$\begingroup\$ the OP was just using that to show that their code works, and not as an actual part of the code. \$\endgroup\$ – Malachi Nov 20 '13 at 23:42
  • \$\begingroup\$ @Malachi is correct, I was just showing that the inheritance works as expected. \$\endgroup\$ – Jack Wilsdon Nov 20 '13 at 23:44
  • 1
    \$\begingroup\$ @jackwilsdon I was quite sure that the ((sub instanceof Class) ? "" : "not ")-part was not necessary, but the things about instanceof can be a good thing to keep in mind for later. \$\endgroup\$ – Simon Forsberg Nov 21 '13 at 0:13
2
\$\begingroup\$

my first impression is that this is a good design and it functions well. I don't know much about the way that Java does Extension, but your code looks well planned and looks like you know the basics of Extension. when you put this into practice on something bigger you should post it as an additional follow-up question (as long as it works) so we can see more of it in action.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.