prototype based vs. class based inheritance

77,223

Solution 1

There are about a hundred terminology issues here, mostly built around someone (not you) trying to make their idea sound like The Best.

All object oriented languages need to be able to deal with several concepts:

  1. encapsulation of data along with associated operations on the data, variously known as data members and member functions, or as data and methods, among other things.
  2. inheritance, the ability to say that these objects are just like that other set of objects EXCEPT for these changes
  3. polymorphism ("many shapes") in which an object decides for itself what methods are to be run, so that you can depend on the language to route your requests correctly.

Now, as far as comparison:

First thing is the whole "class" vs "prototype" question. The idea originally began in Simula, where with a class-based method each class represented a set of objects that shared the same state space (read "possible values") and the same operations, thereby forming an equivalence class. If you look back at Smalltalk, since you can open a class and add methods, this is effectively the same as what you can do in Javascript.

Later OO languages wanted to be able to use static type checking, so we got the notion of a fixed class set at compile time. In the open-class version, you had more flexibility; in the newer version, you had the ability to check some kinds of correctness at the compiler that would otherwise have required testing.

In a "class-based" language, that copying happens at compile time. In a prototype language, the operations are stored in the prototype data structure, which is copied and modified at run time. Abstractly, though, a class is still the equivalence class of all objects that share the same state space and methods. When you add a method to the prototype, you're effectively making an element of a new equivalence class.

Now, why do that? primarily because it makes for a simple, logical, elegant mechanism at run time. now, to create a new object, or to create a new class, you simply have to perform a deep copy, copying all the data and the prototype data structure. You get inheritance and polymorphism more or less for free then: method lookup always consists of asking a dictionary for a method implementation by name.

The reason that ended up in Javascript/ECMA script is basically that when we were getting started with this 10 years ago, we were dealing with much less powerful computers and much less sophisticated browsers. Choosing the prototype-based method meant the interpreter could be very simple while preserving the desirable properties of object orientation.

Solution 2

A comparison, which is slightly biased towards the prototypes based approach, can be found in the paper Self: The Power of Simplicity. The paper makes the following arguments in favor of prototypes:

Creation by copying. Creating new objects from prototypes is accomplished by a simple operation, copying, with a simple biological metaphor, cloning. Creating new objects from classes is accomplished by instantiation, which includes the interpretation of format information in a class. Instantiation is similar to building a house from a plan. Copying appeals to us as a simpler metaphor than instantiation.

Examples of preexisting modules. Prototypes are more concrete than classes because they are examples of objects rather than descriptions of format and initialization. These examples may help users to reuse modules by making them easier to understand. A prototype-based system allows the user to examine a typical representative rather than requiring him to make sense out of its description.

Support for one-of-a-kind objects. Self provides a framework that can easily include one-of-a-kind objects with their own behavior. Since each object has named slots, and slots can hold state or behavior, any object can have unique slots or behavior. Class-based systems are designed for situations where there are many objects with the same behavior. There is no linguistic support for an object to possess its own unique behavior, and it is awkward to create a class that is guaranteed to have only one instance [think singleton pattern]. Self suffers from neither of these disadvantages. Any object can be customized with its own behavior. A unique object can hold the unique behavior, and a separate "instance" is not needed.

Elimination of meta-regress. No object in a class-based system can be self-sufficient; another object (its class) is needed to express its structure and behavior. This leads to a conceptually infinite meta-regress: a point is an instance of class Point, which is an instance of metaclass Point, which is an instance of metametaclass Point, ad infinitum. On the other hand, in prototype-based systems an object can include its own behavior; no other object is needed to breathe life into it. Prototypes eliminate meta-regress.

Self is probably the first language to implement prototypes (it also pioneered other interesting technologies like JIT, which later made its way into the JVM), so reading the other Self papers should also be instructive.

Solution 3

You should check out a great book on JavaScript by Douglas Crockford. It provides a very good explanation of some of the design decisions taken by JavaScript creators.

One of the important design aspects of JavaScript is its prototypal inheritance system. Objects are first class citizens in JavaScript, so much that regular functions are also implemented as objects ('Function' object to be precise). In my opinion, when it was originally designed to run inside a browser, it was meant to be used to create lots of singleton objects. In browser DOM, you find that window, document etc all singleton objects. Also, JavaScript is loosely typed dynamic language (as opposed to say Python which is strongly typed, dynamic language), as a result, a concept of object extension was implemented through the use of 'prototype' property.

So I think there are some pros for prototype-based OO as implemented in JavaScript:

  1. Suitable in loosely typed environments, no need to define explicit types.
  2. Makes it incredibly easy to implement singleton pattern (compare JavaScript and Java in this regard, and you'll know what I am talking about).
  3. Provides ways of applying a method of an object in the context of a different object, adding and replacing methods dynamically from an object etc. (things which are not possible in a strongly typed languages).

Here are some of the cons of prototypal OO:

  1. No easy way of implementing private variables. Its possible to implement private vars using Crockford's wizardry using closures, but its definitely not as trivial as using private variables in say Java or C#.
  2. I don't know how to implement multiple inheritances (for what its worth) in JavaScript yet.
Share:
77,223

Related videos on Youtube

Stefano Borini
Author by

Stefano Borini

Updated on October 12, 2020

Comments

  • Stefano Borini
    Stefano Borini over 3 years

    In JavaScript, every object is at the same time an instance and a class. To do inheritance, you can use any object instance as a prototype.

    In Python, C++, etc.. there are classes, and instances, as separate concepts. In order to do inheritance, you have to use the base class to create a new class, which can then be used to produce derived instances.

    Why did JavaScript go in this direction (prototype-based object orientation)? what are the advantages (and disadvantages) of prototype-based OO with respect to traditional, class-based OO?

    • Aadit M Shah
      Aadit M Shah almost 11 years
      JavaScript was influenced by Self which was the first language with prototypal inheritance. At that time classical inheritance was all the rage, first introduced in Simula. However classical inheritance was too complicated. Then David Ungar and Randall Smith had an epiphany after reading GEB - "The most specific event can serve as a general example of a class of events." They realized that classes are not required for object-oriented programming. Hence Self was born. To know how prototypal inheritance is better than classical inheritance read this: stackoverflow.com/a/16872315/783743 =)
    • Alex
      Alex almost 8 years
      @AaditMShah What/who is GEB?
    • Aadit M Shah
      Aadit M Shah almost 8 years
      @Alex GEB is a book written by Douglas Hofstadter. It's an abbreviation of Gödel Escher Bach. Kurt Gödel was a mathematician. Escher was an artist. Bach was a pianist.
  • John Saunders
    John Saunders about 15 years
    Actually, Simula preceded Smalltalk, and had static type checking as well as inheritance. Simula, in fact, originated the word "Class".
  • Charlie Martin
    Charlie Martin about 15 years
    Right, does that paragaph read as if I meant otherwise? Dahl and Nyqvist came up with "class" as the collection of things with the same method signature.
  • Charlie Martin
    Charlie Martin about 15 years
    Does that change say it better?
  • Thevs
    Thevs about 15 years
    I'd say JavaScript exactly represents CLOS object model, not even Smalltalk or Simula. CLOS was around long before Smalltalk IIRC.
  • Charlie Martin
    Charlie Martin about 15 years
    No, sorry, CLOS is from the late 80's dreamsongs.com/CLOS.html Smalltalk from 1980 en.wikipedia.org/wiki/Smalltalk and Simula with full object orientation from 1967-68 en.wikipedia.org/wiki/Simula
  • Thevs
    Thevs about 15 years
    If could find that paper on "Flavour" - the precessor of CLOS, you'll find out that CLOS is around from late 70's: coding.derkeiler.com/Archive/Lisp/comp.lang.lisp/2004-09/…
  • Charlie Martin
    Charlie Martin about 15 years
  • Thevs
    Thevs about 15 years
    And there was another pre-CLOS system - Common Loops. I'm not quite sure is it also a predator of Smalltalk? Then these two parts (Flavour and CLOOPS) where standartised into CLOS.
  • Stefano Borini
    Stefano Borini about 15 years
    So, as far as I understand, the idea of class based inheritance is more proper of statically typed languages. But then why did python choose this strategy instead of the prototype based one ?
  • Charlie Martin
    Charlie Martin about 15 years
    @Stephano, They're not so distinct as all that: Python, Ruby, Smalltalk use dictionaries for method lookup, and javascript and Self have classes. To some extent, you could argue that the difference is just that the prototype-oriented languages are exposing their implementations. So it's probably good not to make it into a Big Deal: it's probably more like the argument between EMACS and vi.
  • Benedict Cohen
    Benedict Cohen over 13 years
    I remember Joel & Jeff discussing the development of Javascript in one of the SO podcasts. IIRC Javascript was envisaged as a functional language but last minute management panic resulted in OOP stuff being added.
  • Asela Liyanage
    Asela Liyanage over 13 years
    Just use a naming convention for private vars, like Python does.
  • Charlie Martin
    Charlie Martin over 13 years
    Yeah, that was roughly the time when "object oriented" was being used as a synonym for "good". Still, the direct relationship to Self, which was specifically called object-oriented, suggests it's not wrong to say js is OO.
  • Sean McMillan
    Sean McMillan almost 13 years
    In smalltalk, you may add methods to a class, but you may not change the class of an object. (However, you may replace an object with another object, universally.)
  • Max Nanasy
    Max Nanasy over 11 years
    RE: Elimination of meta-regress: In the Common Lisp Object System, which is class-based, a point is an instance of class Point, which is an instance of metaclass standard-class, which is an instance of itself, ad finitum.
  • Benja
    Benja over 11 years
    in js the way to do private vars is with closures, and that's independent of the inheritance type you choose.
  • Adam Arold
    Adam Arold over 10 years
    Useful answer. +1 Less useful junk in the comments. I mean does it make a difference whether CLOS or Smalltalk was first? Most people here are not historians anyway.
  • Cyker
    Cyker over 8 years
    Great answer. Just a question: Can we think of prototype objects as flexible, dynamic class objects?
  • Charlie Martin
    Charlie Martin over 8 years
    Huh, that's an interesting thought. Yeah. Or a class as the equivalence class of all objects with prototypes that share common methods. Oh, and thanks!
  • Hal50000
    Hal50000 over 7 years
    Crockford has done a lot to damage JavaScript, in that a fairly simple scripting language has been morphed into a masterbatory fascination with its internals. JS doesn't have true private keyword scope or true multiple inheritance: don't try to fake them.
  • wallop
    wallop over 5 years
    Excellent answer @CharlieMartin. Your first statement 'There are about a hundred terminology issues here, mostly built around someone (not you) trying to make their idea sound like The Best.' caught my attention. That is what I was thinking from quite sometime but just believed probably I was wrong since there exists so many posts about this. All we can really say is each type has it's advantages and disadvantages and there is no one better than other.
  • user1201917
    user1201917 about 4 years
    Links to a self papers are dead. Working links: Self: The Power of Simplicity | A Self Bibliography