views:

715

answers:

8

If I'm not completely wrong every framework/library/approach in javascript tends today to mimick class based OOP style inheritance. Reasons for this seem to be people thinking class based OOP inheritance is far easier to understand and that most programmers know OOP.

In my experience I don't find evidence for either of this opinions. I think javascript prototypal inheritance is just fine (and I doubt the usefulness to force another paradigm upon a language than the one it is built on). Most of the developers I meet aren't even that good in classical OOP either. So what are the reasons to choose classical OOP style inheritance over prototypal inheritance?

+4  A: 

I think the answer is in your question - most programmers are far more familiar with class-based OOP than prototype-based.

In fact I'd go so far as to say the majority don't believe you can have objects without classes.

Greg
The most developers I encounter aren't very good at prototypal and oop. So it would be just a matter what you learn first. And than I wouldn't try to make another language out of it as it is.I agree that most people see the need for classes to have objects. But javascript has it, too. The names are just differen ;)
Norbert Hartl
A: 

When I was writing my first scripts, it was cool and handy to have such a simple language. But today you do not just want to toggle a buttoncolor, you want to build complex applications in JavaScript. Others might like to use your popular application and would love to see s community providing plugins.

Now, this is much easier to realize with OOP - especially because a lot of programmers a familiar with OOP concepts.

eteubert
That's exactly what I don't understand. Sure if you all agree that most developers are familiar with OOP than I take it. But what makes OOP more powerful than a prototypal approach. Well, I myself find "super" overestimated. So what is it else?
Norbert Hartl
A: 

One reason may be that your server side is likely to be OO (ASP.NET, Java, etc.), so it's just easier to think in the same paradigm on the client. Not necessarily better, but easier.

John M Gant
Well, no. You serialize/marshall your data to some intermediate format. Unmarshalling into something different is IMHO not a problem. Even if you have things that should behave the same on client and server and these are seldom.
Norbert Hartl
@Norbert: just because it's not practical doesn't mean it won't be attempted. See also: WebForms, GWT...
Shog9
+2  A: 

note that even if you're arguing for prototype-based OOP, you call it 'prototypal', and class-based OOP just 'OOP'. so, you yourself suffer from this bias, thinking OOP=>classes, prototypes => something else.

and since most people think that OOP is the right way no matter the problem, then prototypes must be inferior.

so, to answer your question, it's two factors:

  1. a bad definition: "OOP => classes"
  2. propaganda: "it must be OOP, or you're not worthy"

since you're still bounded by the first, you try to explain that prototypes are an exception of the second. much easier is to correct them:

  1. there are many ways to do objects, classes are just the easiest one for static languages. most people are taught to program with static languages, and most of them try to use any language just like the first one they learned.

  2. there are many ways to structure a programming solution, OOP are great at some and lousy at others.

Javier
I don't get what you want to say. I just can't agree to your assumptions about my intentions.
Norbert Hartl
btw. I edited the text so it is hopefully less easy to misinterpret
Norbert Hartl
what i'm saying is that prototype based inheritance is just as OOP as class based inheritance. calling OOP one and not the other reinforces the idea that prototypes are 'not enough', even if you don't believe that, your choice of words works against you.
Javier
Well, then I need to spend some more time to formulate my next question. Thanks for pointing this out.
Norbert Hartl
A: 

I'd argue that the language itself steers people into the classical mindset with it's choice of "new" as a keyword, and by introducing concepts like "constructors" in the language specification. In a way this is limiting - imagine the change in mindset if instead we had a clone keyword, and the concept of traits ala SELF.

OdeToCode
That's a good point. I'm not sure if SELF wouldn't suffer the same as javascript. Well, in self you have to clone but what tells you that there won't be a "new" that would reassemble "clone" + "reset values"? And traits would then be treated as the form of multiple inheritance that is known from C++. Don't you agree?
Norbert Hartl
the history of JavaScript is a sad one: at first it was a variant of Scheme, then it was decided that i had to be more 'procedural', so it borrowed some syntax and keywords from C and C++, and just before launch, it was renamed to fake some relation with Java. in the end, it's the most misleading software. you have to really understand it to start to believe it's not a toy language
Javier
I know that the history of javascript is sad. They were pushed to release, make it look like java and even have that name in there. All the marketing brought somewhat down.
Norbert Hartl
+2  A: 

I feel as if you already know the answer to your question because you stated a part of it when you said

Reasons for this seem to be people thinking class based OOP inheritance is far easier to understand and that most programmers know OOP.

Neither paradigm is more right than the other for tackling a problem. I believe the main reason is that everyone is taught OOP through Java these days. So when people encounter OOP they think "oh classes" because it's what they are familiar with. And whenever they want to solve a problem they will most likely use what they know.

I would also state that it does no benefit for the programmer to use a paradigm he is unfamiliar with. Most of us must use javascript for client side web development and use a class based OOP language on the server. I personally would not want that OOP impedance mismatch whenever I had to look at the javascript side of an application.

At a certain level the fact that everyone is trying to implement class based OOP in javascript is an educational issue. At another level it's a psychological one.

Min
+2  A: 

For a long time I considered prototype-based OOP as weak, bad and wrong version of class-based OOP. Then, after a critical amount of information leaked into my head, I now understand OOP in more abstract way, and find both ways acceptable in general.

Pavel Feldman
A: 

So what are the reasons to choose classical OOP style inheritance over prototypal inheritance? Actually, I believe that some frameworks are "sort of" combining approaches. Take for example the Parasitic Combination Inheritance pattern. This is what YAHOO.lang.extend is doing.

It uses prototypal inheritance and a helper function to inherit prototypes and constructor stealing. Wow, that sounds complex...well yes it is - here's my implementation and test for example:

// Prototypal Inheritance
Object.prototype.inherit = function(p) {
    NewObj = function(){};
    NewObj.prototype = p;
    return new NewObj(); 
};

// Paraphrasing of Nicholas Zakas's Prototype Inheritance helper
function inheritPrototype(subType, superType) {
    var prototype = Object.inherit(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
};
function SubType(name, age) {
    Parent.call(this, name);
    this.age = age;    
};
inheritPrototype(SubType, Parent);  
SubType.prototype.getAge = function() {
    return this.age;
};

I have a test for this code:

   describe 'Parisitic Combination Inheritance'
 it 'should use inheritPrototype (to call parent constructor once) and still work as expected'
     sub = new SubType("Nicholas Zakas", 29)
     sub.toString().should.match /.*Nicholas Zakas/
     sub.getAge().should.eql 29
     charlie = new SubType("Charlie Brown", 69)
     charlie.arr.should.eql([1,2,3])
     charlie.arr.push(999)
     charlie.arr.should.eql([1,2,3,999])
     sub.arr.should.eql([1,2,3]) 
     sub.should.be_an_instance_of SubType
     charlie.should.be_an_instance_of SubType
     (sub instanceof SubType).should.eql true 
     (sub instanceof Parent).should.eql true 
 end
    end

And of course, if you're paying attention to my literals you see: Nicholas Zakas, the guy I got this from ;) The big wins for this one: instanceof works (big deal some say and I kind of agree); instances don't share state on reference types like arrays (a biggie!); parent constructor only called once (a biggie!).

BTW, I have examples of most of the popular inheritance patterns here: My TDD JS Examples

Rob