原型编程的介绍_The Introduction of Prototype-Based Programming

简介

许多编程语言中,函数的原型是声明一个子例程或函数。(这个术语是c/c++特定的;其他的术语,对这一概念是签名、类型和接口).在基于原型的编程(面向对象编程的一种形式),新对象克隆现有的对象称为原型.

该模型也可以称为classless,基于原型或基于实例的编程.委派是是支持基于原型的编程语言的特征.

在基于类的语言中,对象(object)结构是由程序员定义的,指定的类型叫做类(class).当类用来定义数据的类型,对象将具有功能,实例是 基于该模型的具体类的“可用”对象.在这个模型中,类充当集合的行为(method)和结构,对所有实例都是相同的,而实例持有对象的数据.因此这个角色 的区别一方面主要是基于结构和行为之间的区别,另一方面是状态(state).

基于原型编程的主张者经常认为,基于类的语言鼓励一种发展模式,第一集中在分类和类之间的关系上.相比之下,基于原型的编程被视为鼓励程序员关注同 一集合的例子行为,只在后期考虑将这些对象分类到原型对象,之后使用和类就非常的相似.因此,许多基于原型系统鼓励在运行时改变原型,而只有很少的基于类 的面向对象的系统让类能够在执行程序期间改变.

几乎所有的基于原型系统都是基于解释和动态类型语言.系统基于静态类型语言是技术上可行.然而,欧米茄语言在基于原型编程的讨论的一个例子就是这样 的一个系统.但据欧米茄的网站介绍欧米茄不仅仅是静态的,而是它的”编译器可以选择使用静态绑定,这是可能的,并且可以提高程序的效率.”

对象构建

在基于类的语言中,一个新的实例是由类的构造函数创建,一个特定的函数,存储对象成员的一块内存(属性和方法)并返回一个引用块.一组可选的构造函 数参数可以传递数据到函数,数据通常都被属性保管.得到的实例将继承所有的方法和定义类的属性,它作为一种模板,可以构造相似类型对象.

在诸如rhino之类的基于原型的语言没有显式类和直接从其他对象继承的对象,他们通过一个属性联系起来,对于Javascript该属性通常被称为原型(prototype).有两种方法构造新的对象:无中生有ex nihilo(“从什么都没有”)创建对象或通过克隆现有对象.前者是通过某种形式的对象字词提供支持,声明对象的地方都能通过特殊语法如{…}在运行时被定义并直接传递给一个变量.大多数系统都支持各种各样的克隆,无中生有(ex nihilo)对象创建并不那么突出.

支持系统无中生有(ex nihilo)对象创建允许新对象从头开始创建,不从现有的原型克隆.这样的系统提供了一个特殊的语法指定属性和行为且新对象不引用已有对象.在许多原型语言存在一个根对象,通常被称为对象(Object),它被设置为其他对象在运行时创建默认的原型并携带通常需要的方法,如toString()函数来返回一个对象的字符串描述.无中生有(ex nihilo)对象创建一个有用的方面是确保新对象的槽名(slot name)没有和与顶级对象的object的命名空间冲突.(在Mozilla的JavaScript实现中,可以通过设置一个新构造的对象的 proto属性为null来处理).

克隆是指一个过程,一个新对象是通过复制现有对象的行为(它的原型).那么这个新对象带有所有原始对象的特性.从这个点来看,这个新对象可以被修改.在一些系统中生成的子对象维护一个显式的关联(通过 delegation or resemblance)到其原型.原型的变化使得相应的克隆对象发生明显的变化.

委派 Delegation

基于原型语言使用委派,语言运行时能够调度正确的方法或找到正确的数据块的简单地遵循一系列的委派指针(从对象到它的原型)直到找到相匹配的对象. 要求对象之间建立这种共享行为的是委派指针.不像基于类的面向对象的语言中类和实例之间的关系,原型和其分支不需要子对象有一个内存或结构相似的原型超出 这个关联.因此,子对象可以继续进行修改和补充,而不必像基于类的系统一样重新整理相关原型的结构.同样重要的是要注意,不仅仅是数据,方法也可以进行添 加或更改.由于此原因,大部分基于原型的语言涉及的数据和方法都是”槽(slot)”.

串联 concatenative

在纯粹的原型中,这也称为关联(concatenative)的原型.一个对象被复制没有可见的指针或联接(link)到原始的原型.原型对象(prototype object)完全拷贝,但给出一个不同的名称(或引用).行为和属性是简单地重复原有(as-is).

这种方法的一个优势在于,对象的作者可以修改这个副本,而不担心对父级的其他孩子产生副作用.另一个优势是这种方式在分派(dispatch)的时 候查找运算成本比委派(delegation)更低.而找到一个方法或确认一个槽(slot)穷举搜索必须(在失败之前)查找整个委派链 (delegation chain).

不足的是关联(concatenative)方式包括组织难以通过系统传播变化,如果一个变化发生在一个原型,它不会立刻或自动地对其克隆对象可 用.另一个缺点是,在最纯粹的这个模型的实现中,在这一部分的每个克隆增加的内存被浪费了(与委派模型相比),该部分内存使得原型和克隆之间保持一致.

javascript prototype示例:

var base = function(){
}
base.prototype.name = “base”;

var a = new base();
var b = new base();
a.name = “a”;
b.age = 11;
console.info(a.name)
console.info(b.name)
console.info(b.age)
var base = function(){ }
base.prototype.name = “base”;
var a = new base();
var b = new base();
a.name = “a”;
b.age = 11;
console.info(a.name);//out a
console.info(b.name);//out base
console.info(b.age);//out 11

而java中实现原型对象创建则主要是使用clone()克隆:

public abstract class Father implements Cloneable {
public Object clone() {
Object object = null;
try {
object = super.clone();
} catch (CloneNotSupportedException exception) {
System.err.println(“Father is not Cloneable”);
}
return object;
}
}

public class Son extends Father {

public Son(){

this.setName(“hello”);

};

public static void main(String args[]){

Father t = new Son();

Father t2 = (Father) t.clone();//克隆对象

System.out.println(t2.getName());//克隆对象具有方法

}

}