Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Inheritance, Polymorphism, and Encapsulation are the three most distinct, important features of OOP, and from them, inheritance has a high usage statistics these days. I'm learning JavaScript, and here, they all say that it has prototypal inheritance, and people everywhere say that it's something far different from classical inheritance.

However, I can't understand what's their difference from the point of practical usage? In other words, when you define a base class (prototype) and then derive some subclasses from it, you both have access to functionalites of your base class, and you can augment functions on the derived classes. If we consider what I said to be the intended result of inheritance, then why should we care if we're using prototypal or classic version?

To clear myself more, I see no difference in the usefulness and usage patterns of prototypal and classic inheritance. This results in me having no interest to learn why they are different, as they both result in the same thing, OOAD. How practically (not theoretically) prototypal inheritance is different from classical inheritance?

share|improve this question

4 Answers 4

up vote 6 down vote accepted

Recent blog post about JS OO

I believe what your comparing is classical OO emulation in JavaScript and classical OO and of course you can't see any difference.

Disclaimer: replace all references to "prototypal OO" with "prototypal OO in JavaScript". I don't know the specifics of Self or any other implementation.

However prototypal OO is different. With prototypes you only have objects and you can only inject objects into other objects prototype chain. Whenever you access a property on an object you search that object and any objects in the prototype chain.

For prototypal OO there is no notion of encapsulation. Encapsulation is a feature of scope, closures and first class functions but has nothing to do with prototypal OO. There is also no notion of inheritance, what people call "inheritance" is actually just polymorphism.

It does however have polymorphism.

For example

var Dog = {
  walk: function() { console.log("walks"); }
}

var d = Object.create(Dog);
d.walk();

Clearly d has access to the method Dog.walk and this exhibits polymorphism.

So actually there is a big difference. You only have polymorphism.

However as mentioned, if you desired to do so (I have no idea why you would) you can emulate classical OO in JavaScript and have access to (restricted) encapsulation and inheritance.

share|improve this answer
    
@Rayons, Google for prototypical inheritance and you'll see that prototypal inheritance comes up. Even from Yahoo! –  Saeed Neamati Aug 8 '11 at 4:30
    
@Saeed inheritance is a vague term and commonly misused. What they mean with "inheritance" I label "polymorphism". The definitions are too vague. –  Raynos Aug 8 '11 at 8:01
    
No @Rayons, I meant the word prototypal is the correct term, not prototypical. I didn't talk about inheritance :) –  Saeed Neamati Aug 8 '11 at 8:57
1  
@Saeed that's one of those typos my mind just blanks out. I don't pat attention to that –  Raynos Aug 8 '11 at 11:07
1  
Hmm.. terminology. ick. I would call the way that javascript objects are related to their prototypes "delegation". Polymorphism seems to me to be a lower-level concern, based on the fact that a given name may point to different code for different objects. –  Sean McMillan Aug 8 '11 at 19:52

Classical inheritance inherits the behavior, without any state, from the parent class. It inherits the behavior at the moment the object is instantiated.

Prototypal inheritance inherits behavior and state from the parent object. It inherits the behavior and state at the moment the object is called. When the parent object changes at run-time, the state and behavior of the child objects are affected.

The "advantage" of prototypal inheritance is that you can "patch" state and behavior after all your objects are instantiated. For example, in the Ext JS framework it's common to load "overrides" that patch the framework's core components after the framework has been instantiated.

share|improve this answer
3  
In practice, if you're inheriting state, you're setting yourself up for a world of hurt. Inherited state will become shared if it lives on another object. –  Sean McMillan Aug 8 '11 at 19:53
    
It occurs to me that in javascript there really is no concept of behavior separate from state. Aside from the constructor function all behavior can be assigned/modified post-object-creation just like any other state. –  Joeri Sebrechts May 21 '12 at 7:16
    
So Python doesn't have classical inheritance? If I have class C(object): def m(self, x): return x*2 and then instance = C() then when I run instance.m(3) I get 6. But if I then change C so C.m = lambda s, x: x*x and I run instance.m(3) I now get 9. The same goes if I make a class D(C) and change a method on C then any instances of D receive the changed method as well. Am I misunderstanding or does this mean that Python does not have Classical inheritance according to your definition? –  mVChr Aug 8 '13 at 8:34
    
@mVChr: You're still inheriting behavior and not state in that case, which points to classical inheritance, but it does point to an issue with my definition of "inherits the behavior the moment the object is instantiated". I'm not quite sure how to correct the definition. –  Joeri Sebrechts Aug 8 '13 at 11:41

First: Most of the time, you'll be using objects, not defining them, and using objects is the same under both paradigms.

Second: Most prototypal environments use the same kind of division as class based environments -- mutable data on the instance, with methods inherited. So there's very little difference again. (See my answer to this stack overflow question, and the Self Paper Organizing Programs Without Classes. Look at Citeseer for a PDF version.)

Third: Javascript's dynamic nature has a much bigger influence that the kind of inheritance. The fact that I can add a new method to all instances of a type by assigning it to the base object is neat, but I can do the same thing in Ruby, by reopening the class.

Fourth: The practical differences are small, while the practical issue of forgetting to use new is much bigger -- that is, you're far more likely to be affected by missing a new than you are to be affected by the difference between prototypal and classical code.

All that said, the practical difference between prototypal and classical inheritance is that your things-that-hold-methods (classes) are the same as your things-that-hold-data (instances.) This means that you can build up your classes piecemeal, using all the same object manipulation tools that you would use on any instance. (This is, in fact, how all of the class-emulation libraries do it. For a not-quite-like-all-the-others approach, look at Traits.js). This is primarily interesting if you are metaprogramming.

share|improve this answer
    
yay, best answer IMO! –  Aivar May 18 '12 at 22:13

Prototypal inheritance in JavaScript is different from classes in these important ways:

Constructors are simply functions that you can call without new:

function Circle (r, x, y) { 
  //stuff here
}
Var c = new Circle();
Circle.call(c, x, y, z); //This works and you can do it over and over again.

There are no private variables or methods, at best you can do this:

function Circle (r, x, y) {
  var color = 'red';
  function drawCircle () {
    //some code here with x, y and r
  }
  drawCircle();
  this.setX = function (x_) {
    x = x_;
    drawCircle();
  }

}
Circle.prototype.getX = function () {
   //Can't access x!
}

In the previous example you can't extend the class meaningfully if you're resorted to fake private variables and methods and in addition any public methods you've declared will be recreated every time a new instance is created.

share|improve this answer
    
You can extend the "class" meaningfully. You just can't access the local variables color, r, x, y and drawCircle that are bound to the lexical scope of Circle –  Raynos Aug 7 '11 at 22:14
    
It's true, you can, but you can't do it without creating a bunch of 'public' methods added to the context that are created every time you create an instance. –  Bjorn Tipling Aug 7 '11 at 23:27
    
This is a very strange pattern you're using there. Circle.call() as a constructor? It looks like you're trying to describe "functional objects" (a misnomer...) –  Sean McMillan Aug 8 '11 at 19:54
    
It's not something I'd ever do, I'm just saying it is possible to call the constructor over and over again with JavaScript but not in languages with traditional classes. –  Bjorn Tipling Aug 9 '11 at 0:34
1  
But how are these differences 'important'? I don't see constructing objects by calling a function, not using 'new', as 'important', just a small syntax difference. Likewise, not having private variables isn't fundamentally different, just a small difference. Plus, you can have (something similar to) private variables, in the way you describe. –  Roel May 14 '12 at 12:49

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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