views:

1201

answers:

5

Hello, I come from classes object orientation languages and recently I have been learning those fancy dynamic languages (JavaScript, Python and Lua) and I want some tips about how to use OO in those languages. It would be useful to know the pitfalls and the shortcomings of such approach and the advantages compared to traditional OO.

The general notion that I got is that prototype based OO is basically programming with objects but no standard on how to use them whereas in normal OO there is a fixed predefined way to make and use objects.

In summary, what is the good, the bad and the ugly parts of such approach?

A: 

Okay, first of all, the prototype model isn't all that different in reality; Smalltalk uses a similar sort of scheme; the class is an object with the classes methods.

Looked at from the class POV, a class is really the equivalence class of objects with the same data, and all the same methods; you can look at adding a method to a prototype as creating a new subclass.

The implementation is simple, but makes it very difficult to do effective typechecking.

Charlie Martin
+4  A: 

To conserve the bandwidth here is the link to my answer on "What is the best way to emulate “classes” in Javascript? (with or without a framework)". It contains further references as well as examples.

The short answer: the heart of JavaScript's prototypal OO is delegation. In this style of OOP different objects of the same "class" can delegate the handling of methods and properties to the same prototype (usually some 3rd object):

var foo = {
  property: 42,
  inc: function(){
    ++this.counter;
  },
  dec: function(){
    --this.counter;
  }
};
// note: foo doesn't define "counter"

// let's create a constructor for objects with foo as a prototype
// effectively everything unhandled will be delegated to foo

var Bar = function(){
  this.counter = 0;
};
Bar.prototype = foo;  // this is how we set up the delegation

// some people refer to Bar (a constructor function) as "class"

var bar = new Bar();

console.log(bar.counter);  // 0 --- comes from bar itself
console.log(bar.property); // 42 --- not defined in bar, comes from foo

bar.inc();  // not defined in bar => delegated to foo
bar.inc();
bar.dec();  // not defined in bar => delegated to foo
// note: foo.inc() and foo.dec() are called but this === bar
// that's why bar is modified, not foo

console.log(bar.counter);  // 1 --- comes from bar itself

// let's define inc() directly on bar
bar.inc = function(){
  this.counter = 42;
};

bar.inc();  // defined in bar => calling it directly
            // foo.inc() is not even called
console.log(bar.counter);  // 42 --- comes from bar

// setting up the single inheritance chain:

var Baz = function(){
  this.counter = 99;
};
Baz.protype = new Bar();

var baz = new Baz();

console.log(baz.counter); // 99
baz.inc();
console.log(baz.counter); // 100

console.log(baz instanceof Baz);    // true
console.log(baz instanceof Bar);    // true
console.log(baz instanceof Object); // true

Neat, eh?

Eugene Lazutkin
console.log(bar.prototype); shoudn't that be: bar.property ?
Pim Jager
Yep, good catch!
Eugene Lazutkin
+7  A: 

Prototype-based OO lends itself poorly to static type checking, which some might consider a bad or ugly thing. Prototype-based OO does have a standard way of creating new objects, you clone and modify existing objects. You can also build factories, etc.

I think what people like most (the "good") is that prototype-based OO is very lightweight and flexible, offering a very high power-to-weight ratio.

For tips on how to use prototype-based OO, a great place to start is the original Self paper on The Power of Simplicity.

Norman Ramsey
+1  A: 

Before worrying about how to emulate class-based inheritance in Javascript, have a quick read of this : http://javascript.crockford.com/prototypal.html

interstar
A: 

Classical inheritance is inherently flawed in terms of flexibility, in that we are saying "this object is of this type and no other". Some languages introduce multiple inheritance to alleviate this, but multiple inheritance has its own pitfalls, and so the benefits of pure composition over inheritance (which, in a statically typed language, is a runtime rather than a compile time mechanism) become clear.

Taking the concept of composition to this "pure" level, we can eliminate classical inheritance altogether along with static typing. By composing objects at runtime and using them as blueprints (the prototypal approach), we need never concern ourselves with boxing objects too tightly through inheritance, nor burden ourselves with the issues inherent in multiple inheritance approaches.

So prototypal means much more flexible development of modules.

Of course, it's quite another thing to say it's EASY to develop without static typing. IMO, it is not.

Nick Wiggill