CSC/ECE 517 Fall 2010/ch2 2c hy

From Expertiza_Wiki
Jump to navigation Jump to search
Prototype Based Inheritance

Introduction

Prototype inheritance is a style of behaviour reuse in object oriented programming language. Different form class based programming, prototype programming builds new object from existing one calling as a prototype object. The new object will carry all the behaviour, data structure and values from the old object. Although different language will impose different limits, the new object is typically free to modify. This is clearly different from class based inheritance where all the objects built from the same class will have the same structure.

Different types of prototype-based inheritance

Delegation in Ruby

The key feature of delegation is the delegation link created between the parent object and the child object. The child object does not actually inherited the data and method into its local memory, but rather creates a link pointing to the data and method of its parent object. In Ruby, the implementation of prototype inheritance lies mostly, if not entirely, on the Object.extend method. The modification to an object is exclusively carried out through Object.extend method. This method dosen't actually change the object except adding a delegation link to another part of code. In Ruby this referred code is a module. From module's point of view, the new object is its offspring with a delegation scheme inheritance. The mechanism underlying the delegation is a rule of method search through connected delegation link at runtime. This is depend on dynamic binding that help to determine which method will be called at runtime. Therefore, type casting and method validity will not be checked at compile time and any changes to the module will immediately influence all its offsprings.

Concatenation in Ruby

Except the delegation scheme realized in extend method, there is another prototype inheritance scheme called concatenation. In concatenation, the ascendant object will take up new memory space with prototype copied exactly and there is no link or pointer to the prototype object. The method and data are keeping local, sparing the search time in runtime. The changes being made with child will have no effect to its parents. On the contrary, whether the changes to its parents could possibly apply to the child depends on the language support and the way we generate the child object. Concatenation could also be done with Ruby, but in a slightly curved way. We can first copy prototype to a new object or memory space, then complete it with the changes through extend method. The child object has no link to its parents and is keeping all the data and method from its parent local. But as the delegation link pointing to a module is still used as runtime, it will go with the drawback of the runtime search. And as it is implemented through programmer controlled copy action, Ruby is not likely provide changes propagation from the parent to its child.

Implementation of prototype-based inheritance

In this section, we will briefly introduce how to implement prototype-based inheritance in different programming languages. Specifically, we consider three programming languages, Ruby, JavaScript, and ActionScript.

Prototype-based inheritance in Ruby

Ruby can be a class-based language, in which inheritance is achieved by defining classes of objects. But Ruby can also act as a prototype-based language by using Object.extend method.
Here’s an example of prototype-based inheritance in Ruby [1]. In the example, we define a mild-mannered Person class.


class Person
  attr_reader :name, :age, :occupation

   def initialize(name, age, occupation)
     @name, @age, @occupation = name, age, occupation
   end

   def mild_mannered?
     true
   end
end

jimmy = Person.new('Jimmy Olsen', 21, 'cub reporter')
clark = Person.new('Clark Kent', 35, 'reporter')
puts jimmy.mild_mannered?
puts clark.mild_mannered?

>> true
>> true

But there are some Person objects that are not as mild-mannered as they appear. They have super powers.

module SuperPowers
  def fly
    'Flying!'
  end

  def leap(what)
     "Leaping #{what} in a single bound!"
  end

  def mild_mannered?
     false
  end

  def superhero_name
    'Superman'
  end
End

We use ‘Object.extend’ method to give super powers to certain people.


clark.extend(SuperPowers)
puts clark.superhero_name
puts clark.fly         
puts clark.leap("100 ft")
puts clark.mild_mannered?                   
puts jimmy.mild_mannered?

>> Superman
>> Flying!
>> Leaping 100 ft in a single bound!
>> false
>> true

We give another simple example [2].


Fred = Module.new do
  def meth1
    "hello"
  end
  
  def meth2
    "bye"
  end
end

a = "my string"
a.extend(Fred)
puts a.meth1
puts a.meth2

>> hello
>> bye

Prototype-based inheritance in JavaScript

JavaScript is an implementation of the ECMAScript language standard and is typically used to enable programming access to computational objects within a host environment. Prototype-based inheritance is probably the most common form of JavaScript class inheritance. It's not really much of a pattern because this is essentially the approach that was built into the language by its creators. The 'prototype' member exists on all JavaScript objects and since all functions in the language are object instances, you can access the prototype member of any function that has been defined.

Here’s an example of prototype-based inheritance in JavaScript [3].

function BaseClass() {
    //BaseClass constructor code goes here 
}

BaseClass.prototype.getName = function() {
    return "BaseClass";
}

function SubClass() {
    //SubClass constructor code goes here 
}

//Inherit the methods of BaseClass
SubClass.prototype = new BaseClass();

//Override the parent's getName method
SubClass.prototype.getName = function() {
    return "SubClass";
}

//Alerts "SubClass"
alert(new SubClass().getName());

Prototype-based inheritance in ActionScript

ActionScript is a scripting language developed by Adobe. It is a dialect of ECMAScript, and is used primarily for the development of websites and software targeting the Adobe Flash Player platform.
Here’s an example of prototype-based inheritance in ActionScript [4].

//Define the original classpublic class myClass {
      public function function1() {
     trace ("I am the original function1!"); 
   }//function1
}//myClass
//Create a class that updates the prototype!
import myClass;
public class updateClass {
      public function updateClass() {
      myClass.prototype.function1=function() {
        trace ("I am a new function1. The old one is gone!");
     }//prototype
   }//constructor
}//updateClass
//Now we extend the previous class
import myClass;
public class extendingClass extends myClass {
   public function extendingClass() {
     this.function1();
   }//constructor
}//extendingClass

By affecting the prototype of the myClass class, we are updating the very top class itself and any classes that extend it are automatically updated as well.

Advantages and disadvantages of prototype-based inheritance

Change behaviour of objects outside class definition brings risks and also new features. Typically, we could build from specific instance and develop it later into more general category, rather than first killing our brain to think though each and every corner of the blue print to ensure a good behaviour. Things you can easily prompt up with a blue print are usually easy staffs. Recall the laboratory doing the most novel experiment, always at a mess. Why? As you cannot predict what would be taken care later on, how could you set up a blue print to keep order of them. Not going to the ends, bearing in mind that we still need an adapted design pattern to ensure a controllable mess.


Therefore, in prototype-based inheritance there are two big advantages, simplicity and correctness. Simple since the concept of class is eliminated and rather than having class inheritance. Further, it is more concrete since programming one modifies the objects directly and not class indirectly to achieve the effect on an object [5].


The disadvantage of prototype-based inheritance is that the code becomes hard to control. For example, in delegation design pattern, it can inadvertently modify a critical function that another extending class may be depending on (see example in ActionScript). This can lead to subtle bugs. This is referred to as the prototype corruption problem [6].


Conclusion

We have briefly reviewed the prototype-based inheritance. The main characteristic of prototype-based inheritance is the fact that it is classless. Prototype-based inheritance can be implemented in many different programming languages including Ruby, JavaScript and ActionScript. At last, we have shown that prototype-based inheritance possesses some advantages and disadvantages.

References

1] ECE 517 lecture notes
[2] Programming Ruby The Pragmatic Programmers Guide 2nd Ed
[3] http://ajaxpatterns.org/Javascript_Inheritance
[4] http://www.actionscript.org/resources/articles/773/1/Prototype-and-Class-Inheritance-Differences-and-Uses/Page1.html
[5] Walter R. Smith, Using a Prototype-based Language for User Interface: The Newton Project’s Experience http://wsmith.best.vwh.net/OOPSLA95.pdf
[6] http://www.idt.mdh.se/kurser/cd5130/msl/2005lp4/downloads/reports/prototype_based_languages.pdf