view source/classes.rst @ 213:0ea90a1819c2 default tip

Custom theming
author Radomir Dopieralski <radomir.dopieralski@allegro.pl>
date Wed, 27 Jun 2012 16:35:54 +0200
parents 4e6cfa066d1a
children
line wrap: on
line source

Classes
=======

In Python, *class* is a language primitive.  JavaScript has no
built-in concept of class.  Therefore, if we are to have classes in
JavaScript then we (or some library) must implement them.  Here we
give an outline implementation of classes in JavaScript, so that the
basic language features can be understood.

:ref:`Recall <inheritance-tree>` that each object has a parent, which
in turn has a parent, all the way up to the root object (which has no
parent).  In Python (and other languages), classes are a way for
instances to share data and methods.  As a first approximation, let us
say *two objects belong to the same class if they have the same
parent*.

As well as sharing class data, each instance of a class has its own
data, which is added to the instance as part of its creation.  In
Python, this is usually done using the ``__init__`` method (although
sometimes ``__new__`` is also used).

Point in Python
---------------

In Python we might write:

.. code-block:: python

   class Point(object):

       def __init__(self, x, y):
           self.x = x
           self.y = y

       def move(self, dx, dy):
          '''Move point by changes dx and dy.'''
           self.x += dx
           self.y += dy

   mypoint = Point(2, 3)
   mypoint.move(1, 1)


Point in JavaScript
-------------------

To implement a similar class in JavaScript we need a function Point
that returns a point, and an object that is a parent for all the
points created by the ``Point`` function.  In Python we had a single
object, namely the class ``Point``, that performed both roles.  In
JavaScript we need a constructor function and a parent object.


Parent object
^^^^^^^^^^^^^

We'll start with the parent object:

.. code-block:: javascript

   var base = {};               // Grandparent for all instances.
   var point = create(base);    // Parent to all points.

   point.__init__ = function(x, y){
       this.x = x;
       this.y = y;
   };

   point.move = function(dx, dy){
       this.x += dx;
       this.y += dy;
   };

See [link] for why we use ``this`` rather than ``self``.


Constructor
^^^^^^^^^^^

We also need a constructor function

.. code-block:: javascript

   var Point = function(x, y){

       var instance = create(point);
       instance.__init__(x, y);
       return instance;
   };


In production we would use ``arguments`` and ``apply`` rather than
directly calling ``__init__``.  Do you know why?

Advanced features
-----------------

This can be omitted at a first reading.

Improved ``toString``
^^^^^^^^^^^^^^^^^

In Python we have, for example:

.. code-block:: python

   py> from point import Point
   py> Point(2, 3)
   <point.Point object at 0x20ead90>

We can get something similar in JavaScript by writing:

.. code-block:: javascript

   point.__classname__ = 'Point';
   base.toString = function(){
       return '<' + this.__classname__ + ' object>'
   };

Constructor factory
^^^^^^^^^^^^^^^^^^^

Here is a factory function for producing constructor functions,
such as ``Point`` above.

.. code-block:: javascript

   var constructor_factory(parent){
       return function(){
           var instance = create(parent);
           instance.__init__.apply(instance, arguments);
           return instance;
       };
   };

   var Point = constructor_factory(point);