32

I am a programmer who has programmed in several languages, both functional and OO oriented. I programmed some Javascript too, but never used (or had to use) polymorphism in it.

Now, as kind of a hobby project, I would like to port some apps that were written in Java and C# that heavily use polymorhpism to Javascript.

But at a first glance I read lots of 'It's possible but ...'

So is there an alternative to it?

An example of what I would like to write in JS in pseudolang :

abstract class Shape{ { printSurface() } ;  }

class Rect : Shape() {  printSurface() { print (sideA*sideB}}

class Circle : Shape() {  printSurface() { print { pi*r*r }}

TheApp { myshapes.iterate(shape s) {s.printSurface() } }

So a classic polymorphic case : iterating over baseclass.

I would like to achieve this kind of behaviour. I know it is polymorhism, but are there any other 'patterns' that I am overlooking that achieve this kind of behaviour or should I study the inheritance possibilities in Javascript?

5 Answers 5

43

As said, JavaScript is a dynamic typed language based on prototypal inheritance, so you can't really use the same approach of typed languages. A JS version of what you wrote, could be:

function Shape(){
  throw new Error("Abstract class")
}

Shape.prototype.printSurface = function () {
  throw new Error ("Not implemented");
}

function Rect() {
  // constructor;
}

Rect.prototype = Object.create(Shape.prototype);
Rect.prototype.printSurface = function() {
  // Rect implementation
}

function Circle() {
  // constructor;
}

Circle.prototype = Object.create(Shape.prototype);
Circle.prototype.printSurface = function() {
  // Circle implementation
}

Then, in your app:

var obj = new Circle();

if (obj instanceof Shape) {
    // do something with a shape object
}

Or, with duck typing:

if ("printSurface" in obj)
    obj.printSurface();

// or

if (obj.printSurface)
    obj.printSurface();

// or a more specific check
if (typeof obj.printSurface === "function")
    obj.printSurface();

You cold also have Shape as object without any constructor, that it's more "abstract class" like:

var Shape = {
    printSurface : function () {
        throw new Error ("Not implemented");
    }
}

function Rect() {
  // constructor;
}

Rect.prototype = Object.create(Shape);
Rect.prototype.printSurface = function() {
  // Rect implementation
}

function Circle() {
  // constructor;
}

Circle.prototype = Object.create(Shape);
Circle.prototype.printSurface = function() {
  // Circle implementation
}

Notice that in this case, you can't use instanceof anymore, so or you fallback to duck typing or you have to use isPrototypeOf, but is available only in recent browsers:

if (Shape.isPrototypeOf(obj)) {
    // do something with obj
}

Object.create is not available in browser that doesn't implement ES5 specs, but you can easily use a polyfill (see the link).

Sign up to request clarification or add additional context in comments.

2 Comments

Tx, very nice answer. But pragmatically, I will go for JOOSE, the classframework.
This doesn't work for Document. I wanted to create NMLDocument which inherits from Document but a weird [LenientThis] error came out.
13

The "pattern" in play here would be "interface". As long as all the objects in the myshapes collection implement the printSurface() method, you will be fine.

Since Javascript is a dynamically typed language, the objects in a collection don't need to be related at all.

2 Comments

Even the same example I used is shown here : knol.google.com/k/…
I don't get why this answer is not upvoted more. It points out the simple truth about JavaScript and that's polymorphism is just naming properties the same. There aren't any type constraints to worry about.
8

i know this can be done with prototypes but i am not a master of using it. i prefer the object literal approach (easier to visualize and has a "private" scope)

//shape class
var shape = function() {
    //return an object which "shape" represents
    return {
        printSurface: function() {
            alert('blank');
        },
        toInherit: function() {
            alert('inherited from shape');
        }
    }
};

//rect class
var rect = function() {
    //inherit shape
    var rectObj = shape();

    //private variable
    var imPrivate = 'Arrr, i have been found by getter!';

    //override shape's function
    rectObj.printSurface = function(msg) {
        alert('surface of rect is ' + msg);
    }

    //you can add functions too
    rectObj.newfunction = function() {
        alert('i was added in rect');
    }

    //getters and setters for private stuff work too
    rectObj.newGetter = function(){
        return imPrivate;
    }

    //return the object which represents your rectangle
    return rectObj;
}



//new rectangle
var myrect = rect();

//this is the overridden function
myrect.printSurface('foo');

//the appended function
myrect.newfunction();

//inherited function
myrect.toInherit();

//testing the getter
alert(myrect.newGetter());

2 Comments

I have to see in to it later, but always +1 for so who does the effort to provide codedamples!
@Weston : isn't that on subject enough to be a separate answer? The frameworks can be discussed there than. For now : is the performance penalty always acceptable?
4

As Weston says, if you don't have the need for inheritance then the duck-typed nature of a dynamic language such as Javascript gives you polymorphism since there is no requirement in the language itself for a strongly typed base class or interface.

If you do want to use inheritance and do things like calling a superclass's implementation easily then this can be achieved with prototypes or object literals as shown by Joeseph.

Another thing would be to look at Coffescript since this compiles down to Javascript giving you all the OO goodness in a simple syntax. It will write all of the bollerplate prototyping stuff for you. The disadvantage is that it adds this extra compilation step. That said writing a simple class hierarchy like your example above and then seeing what javascript pops out as a result helps show how it can all be done.

Comments

4

On another note. If you want to program Javascript in an OO style using classes, you could look into the many "class-systems" for Javascript. One example is Joose (http://joose.it).

Many client side frameworks implement their own class system. An example of this is ExtJS.

2 Comments

trying it now, it's really very nice
Or just forget about classes and embrace the objects.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.