CSC/ECE 517 Fall 2010/ch2 2c hy
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 modification is exclusively carried out through extend method by referring the changes to a module. 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. The mechanism underlying 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. To create a ascendant, we need first copy prototype to a new object or memory space, then complete it with the changes through extend method.
Concatenation
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. This concept could be implemented in Ruby indirectly. First copy an object, then use extend method making change to the newly build ascendant. But as the extend method are using a delegation link as runtime search path, it will be with the drawback of 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