在基于原型的语言维基百科文章包含以下内容:
几乎所有基于原型的系统都基于解释型和动态类型化的语言。但是,基于静态类型语言的系统在技术上是可行的。
静态类型系统以什么方式对基于原型的语言施加限制或引入复杂性,为什么会有更多动态类型的原型语言?
在基于原型的语言维基百科文章包含以下内容:
几乎所有基于原型的系统都基于解释型和动态类型化的语言。但是,基于静态类型语言的系统在技术上是可行的。
静态类型系统以什么方式对基于原型的语言施加限制或引入复杂性,为什么会有更多动态类型的原型语言?
Answers:
基本类型和对象之间的边界是模糊的,通常是人为引入的。例如,在C中,结构只是一堆记录,只是一个派生的非对象类型。在C ++中,结构是具有所有公共字段(一个对象)的类。尽管如此,C ++几乎完全与C向后兼容...这里的边界确实很柔和。
对于基于原型的编程,您需要在运行时使对象可变。它们必须是软类型的,因为每种类型都会在运行时更改,一种类型的类会更改为另一种类型-它的类型也会更改。
您可以将基本和派生的非对象类型保持为静态。但这引入了怪异的差异,对象是软类型的,非对象是静态类型的,并且必须在两者之间建立硬屏障。您应该能够变形结构吗?弦吗?Number应该是一个类或基本类型,还是一组基本类型,例如int / float / bignum / etc?
统一,所有类型都是可变的或在运行时没有类型是可变的,这是更自然,更容易学习,使用和编写的。如果您只声明一种类型(对象)是可变的,那么您将面临着两个世界的头痛和麻烦。
静态类型为:
动态类型为:
通过将两者融合在一起,您可以牺牲很多。
看到的困难非常简单:将对象视为方法的字典或响应消息的事物,请注意以下有关常见的静态类型的OO语言的内容:
通常,所有字典键/消息都是使用静态声明的标识符预先声明的。
预先声明了某些消息集,并且将对象与这些集合关联以确定它们响应的消息。
一组消息是另一组消息的子集的包含关系被静态且显式声明;未声明,但逻辑子集无效。
类型检查尝试确保所有消息仅发送给响应它们的对象。
这些冲突中的每一个在某种程度上都与基于原型的系统冲突:
可以预先声明消息名称,形式为“原子”,插入字符串或其他形式,仅此而已;对象的可塑性意味着将类型分配给方法很麻烦。
可以说,这是基于原型的系统的基本功能,即消息集是由对象的响应定义的,而不是相反的。在编译时将别名分配给特定组合是合理的,但是在运行时确定的消息集必须是可能的。
以上两个因素的真正影响在于包含关系,其中显式声明是完全不可行的。静态,名义子类型意义上的继承与基于原型的系统相反。
这给我们带来了最后一点,我们并不真的想改变。我们仍然希望确保仅将消息发送到响应它们的对象。然而:
那么如何解决呢?要么以某种方式限制全部通用性(这是令人不愉快的,并且可以首先扼杀使用基于原型的系统的任何好处),要么使类型系统更加灵活并表达约束而不是确切的类型。
基于约束的类型系统很快导致了结构子类型的概念,在非常宽松的意义上,可以将其视为“鸭子类型”的静态等效项。这里最大的障碍是这种系统的类型检查要复杂得多,并且知名度也较低(这意味着很少要研究的工作)。
总结:有可能,它比标称静态类型系统或基于运行时元数据的动态系统难做,因此很少有人在意。
我相信实现静态类型的,基于原型的语言的一种方法是使该语言基于“模板和概念”。
概念曾经是C ++ 0x的计划功能。实际上,C ++模板中的通用代码已经是“静态鸭子式的”。Concepts的想法是能够说出有关所需成员和类型特征的一些信息,而无需或暗示该关系所基于的类继承模型(因为它必须与已经“静态转换为鸭子”的现有模板代码一起使用) )。
使用完全基于模板和概念的语言,这将是基于原型的概念,并且模板将使您不必担心任何可能用于或可能不用于实现值类型的类模型。
除了使用分阶段编译使该语言成为其自身元语言的技巧外,这些概念的原型派生一旦创建就必然是不可变的。但是,反对不是基于原型的说法是“红色鲱鱼”。它只是一种功能语言。至少已经尝试了一种具有动态功能且基于原型的语言。