CSC/ECE 517 Fall 2014/ch1b 30 cs: Difference between revisions
No edit summary |
No edit summary |
||
(6 intermediate revisions by the same user not shown) | |||
Line 3: | Line 3: | ||
Prototype-based programming is an alternative approach to creating objects, where instead of a class, they get their properties from other objects<ref name="moz" />. | Prototype-based programming is an alternative approach to creating objects, where instead of a class, they get their properties from other objects<ref name="moz" />. | ||
As an example, consider creating an object in a class-based approach. We would define a <tt>Class</tt> that contains the variable <tt>var1</tt> and function <tt>func1()</tt>. Then within the class we would define a constructor, which will create <tt>Object</tt> which can access <tt>func1()</tt> and may have a value assigned to <tt>var1</tt> | As an example, consider creating an object in a class-based approach. We would define a <tt>Class</tt> that contains the variable <tt>var1</tt> and function <tt>func1()</tt>. Then within the class we would define a constructor, which will create <tt>Object</tt> which can access <tt>func1()</tt> and may have a value assigned to <tt>var1</tt>. On the other hand, in a prototype-based approach we would just create an object from a ''prototype'' containing <tt>var1</tt> and <tt>func1()</tt>, without the need for a class file or declaration. | ||
== Benefits and Drawbacks == | == Benefits and Drawbacks == | ||
Classes and prototypes are commonly seen as not strictly better than the other, but rather just appropriate for different situations<ref name="shah" /><ref name="se1" />. Prototypes offer more flexibility | Classes and prototypes are commonly seen as not strictly better than the other, but rather just appropriate for different situations<ref name="shah" /><ref name="se1" />. Prototypes offer more flexibility in object creation and modification, without needing separate classes for each variation. Thus, creating clones or descendants of objects can be accomplished with less code. However, your code might not be as structured without centralized classes, and you may be giving up benefits of static typing. | ||
Examples of class-based languages are Java and C++. The most popular prototype-based language is JavaScript, but some other examples are Io<ref name="io" />, REBOL<ref name="rebol" /> and Self<ref name="self" />. | Examples of class-based languages are Java and C++. The most popular prototype-based language is JavaScript, but some other examples are Io<ref name="io" />, REBOL<ref name="rebol" /> and Self<ref name="self" />. | ||
== Prototypes in JavaScript == | == Prototypes in JavaScript == | ||
Although JavaScript is a prototype-based language, its syntax can give the appearance of being class-based, e.g. | Although JavaScript is a prototype-based language, its syntax can give the appearance of being class-based, e.g. | ||
<pre> | <pre> | ||
function Student( | function Student(Name, Id) { | ||
this. | this.id = Id; | ||
this. | this.name = name; | ||
this. | this.addToCourse = function(course) { | ||
console.log("Added " + this.name + " to " + course + "!"); | |||
}; | }; | ||
} | } | ||
var james = new Student("James Jones", 200031416); | |||
</pre> However, this does ''not'' create an object of a <tt>Student</tt> class<ref name="pivotal" />. Also note that there is nothing special about the <tt>Student</tt> function that makes it a "constructor"<ref name="wald" />. Instead, we use the <tt>new</tt> keyword before the function call to signify that a new object is being created. The <tt>james.constructor</tt> property of our new object is set to the <tt>Student</tt> function, and then the function runs while treating <tt>this</tt> as the new object. | |||
Perhaps more true to a prototype-based style would be to start with our first object: | |||
<pre> | |||
var james = { | |||
id: 200031416, | |||
name: "James Jones", | |||
addToCourse : function(course) { | |||
console.log("Added " + this.name + " to " + course + "!"); | |||
} | |||
}; | |||
</pre> | </pre> | ||
We can then create a copy of this object: | |||
<pre> | <pre> | ||
var susan = Object.create(james); | |||
susan.name = "Susan Smith"; | |||
susan.addToCourse("CSC 505"); // Added Susan Smith to CSC505! | |||
james.addToCourse("CSC 517"); // Added James Jones to CSC517! | |||
</pre> | </pre> | ||
And freely change it without affecting the original: | |||
<pre> | |||
susan.semesterCreditLimit = 13; | |||
console.log(susan.semesterCreditLimit); // 13 | |||
console.log(james.semesterCreditLimit); // undefined | |||
susan.addToCourse = "This was supposed to be a function"; | |||
console.log(susan.addToCourse); // This was supposed to be a function | |||
</pre> | |||
== Prototypes in Ruby == | == Prototypes in Ruby == | ||
<ref name="rubyproto" /> | Although Ruby is a class-based language, its dynamic nature allows some similarity between prototype-based languages<ref name="rubyproto" />. We can take advantage of singleton classes<ref name="singleton" /> to recreate our previous JavaScript program: | ||
<pre> | |||
class Student | |||
attr_accessor :name, :id | |||
def initialize(name, id) | |||
@name = name | |||
@id = id | |||
end | |||
def add_to_course(course) | |||
puts "Added " + name + " to " + course + "!" | |||
end | |||
end | |||
james = Student.new "James Jones", 200031416 | |||
susan = james.clone | |||
class << susan | |||
attr_accessor :semester_credit_limit, :add_to_course | |||
end | |||
susan.semester_credit_limit = 13 | |||
james.semester_credit_limit = 13 # NoMethodError | |||
susan.add_to_course = "This was supposed to be a function" | |||
puts susan.semester_credit_limit # 13 | |||
puts susan.add_to_course # This was supposed to be a function | |||
</pre> | |||
== References == | == References == | ||
Line 44: | Line 94: | ||
<ref name="self">[http://selflanguage.org/ Self]</ref> | <ref name="self">[http://selflanguage.org/ Self]</ref> | ||
<ref name="pivotal">[http://pivotallabs.com/javascript-constructors-prototypes-and-the-new-keyword/ Pivotal Labs, "JavaScript constructors, prototypes, and the `new` keyword"]</ref> | <ref name="pivotal">[http://pivotallabs.com/javascript-constructors-prototypes-and-the-new-keyword/ Pivotal Labs, "JavaScript constructors, prototypes, and the `new` keyword"]</ref> | ||
<ref name="wald">[http://raganwald.com/2013/02/10/prototypes.html Ragan Wald, "Classes vs. Prototypes in JavaScript"]</ref> | |||
<ref name="rubyproto">[https://practicingruby.com/articles/adventure-in-prototypes Avdi Grimm, "An Adventure in Prototypes"]</ref> | <ref name="rubyproto">[https://practicingruby.com/articles/adventure-in-prototypes Avdi Grimm, "An Adventure in Prototypes"]</ref> | ||
<ref name="singleton">[http://www.devalot.com/articles/2008/09/ruby-singleton Peter Jones, "Understanding Ruby Singleton Classes"]</ref> | |||
</references> | </references> |
Latest revision as of 04:02, 14 October 2014
Prototype-based Programming
Most people are familiar with class-based languages, in which to create an object, one defines a class containing functions and variables, and then objects are instantiated from the class. Prototype-based programming is an alternative approach to creating objects, where instead of a class, they get their properties from other objects<ref name="moz" />.
As an example, consider creating an object in a class-based approach. We would define a Class that contains the variable var1 and function func1(). Then within the class we would define a constructor, which will create Object which can access func1() and may have a value assigned to var1. On the other hand, in a prototype-based approach we would just create an object from a prototype containing var1 and func1(), without the need for a class file or declaration.
Benefits and Drawbacks
Classes and prototypes are commonly seen as not strictly better than the other, but rather just appropriate for different situations<ref name="shah" /><ref name="se1" />. Prototypes offer more flexibility in object creation and modification, without needing separate classes for each variation. Thus, creating clones or descendants of objects can be accomplished with less code. However, your code might not be as structured without centralized classes, and you may be giving up benefits of static typing.
Examples of class-based languages are Java and C++. The most popular prototype-based language is JavaScript, but some other examples are Io<ref name="io" />, REBOL<ref name="rebol" /> and Self<ref name="self" />.
Prototypes in JavaScript
Although JavaScript is a prototype-based language, its syntax can give the appearance of being class-based, e.g.
function Student(Name, Id) { this.id = Id; this.name = name; this.addToCourse = function(course) { console.log("Added " + this.name + " to " + course + "!"); }; } var james = new Student("James Jones", 200031416);
However, this does not create an object of a Student class<ref name="pivotal" />. Also note that there is nothing special about the Student function that makes it a "constructor"<ref name="wald" />. Instead, we use the new keyword before the function call to signify that a new object is being created. The james.constructor property of our new object is set to the Student function, and then the function runs while treating this as the new object.
Perhaps more true to a prototype-based style would be to start with our first object:
var james = { id: 200031416, name: "James Jones", addToCourse : function(course) { console.log("Added " + this.name + " to " + course + "!"); } };
We can then create a copy of this object:
var susan = Object.create(james); susan.name = "Susan Smith"; susan.addToCourse("CSC 505"); // Added Susan Smith to CSC505! james.addToCourse("CSC 517"); // Added James Jones to CSC517!
And freely change it without affecting the original:
susan.semesterCreditLimit = 13; console.log(susan.semesterCreditLimit); // 13 console.log(james.semesterCreditLimit); // undefined susan.addToCourse = "This was supposed to be a function"; console.log(susan.addToCourse); // This was supposed to be a function
Prototypes in Ruby
Although Ruby is a class-based language, its dynamic nature allows some similarity between prototype-based languages<ref name="rubyproto" />. We can take advantage of singleton classes<ref name="singleton" /> to recreate our previous JavaScript program:
class Student attr_accessor :name, :id def initialize(name, id) @name = name @id = id end def add_to_course(course) puts "Added " + name + " to " + course + "!" end end james = Student.new "James Jones", 200031416 susan = james.clone class << susan attr_accessor :semester_credit_limit, :add_to_course end susan.semester_credit_limit = 13 james.semester_credit_limit = 13 # NoMethodError susan.add_to_course = "This was supposed to be a function" puts susan.semester_credit_limit # 13 puts susan.add_to_course # This was supposed to be a function
References
<references> <ref name="moz">Mozilla Developer Network, "Details of the Object Model"</ref> <ref name="shah">Aadit Shah, "Why Prototypal Inheritance Matters"</ref> <ref name="se1">Programmers Stack Exchange, "What are the advantages of prototype-based OOP over class-based OOP?"</ref> <ref name="io">Io</ref> <ref name="rebol">REBOL - Objects</ref> <ref name="self">Self</ref> <ref name="pivotal">Pivotal Labs, "JavaScript constructors, prototypes, and the `new` keyword"</ref> <ref name="wald">Ragan Wald, "Classes vs. Prototypes in JavaScript"</ref> <ref name="rubyproto">Avdi Grimm, "An Adventure in Prototypes"</ref> <ref name="singleton">Peter Jones, "Understanding Ruby Singleton Classes"</ref> </references>