一个真实的对象(第二部分)

本文翻译自IronPython的作者Jim Hugunin的个人博客,原文链接为http://blogs.msdn.com/hugunin/archive/2007/05/04/the-one-true-object-part-2.aspx
 
DLR的类型系统核心是基于向对象传递消息的。这完全不是一个新的想法,而是某些面向对象系统的智能核心。这个简单的想法根本不去显式的讨论类型,而是关心对象和消息。每一个静态或动态语言有自己的对象是什么的概念:从C#的静态单继承类型到Python的动态多继承类型再到JavaScript的原型。使这些不同的系统在类型层次相互谐调是相当复杂的——而且可以有一些要到DLR v2去解决。尽管有这些类型层次的差异,当你从基于对象的消息传递层面来看待它们,所有这些语言有极大的共性。
 
为了用这种类型系统来支持广泛的语言,我们需要一些清楚的定义标准消息集合,使得所有的语言都能够响应。这个集合应该足够丰富,能够捕捉所有我们用的不同语言的独特改制,同时要还十分公用,使得不同语言的代码能够相互协作。这是一个我们要来协调的平衡,当我们引入更多的语言时。但是我想我们已经有了一个在引入的最初的四种语言中,我们已经有了优秀的开端和成功。下而是我们当前的操作集合。
  • [Get|Set|Delete]Member(name, case-sensitivity) – 取出, 设置或删除一个对象的有名字的成员。
  • Call/CreateInstance(argument modifiers) – 对一个对象的带有参数的标准调用或’new’调用。
  • SimpleOperation(OperationKind enumeration) – 包含所有的简单公用操作,比如加、减、索引。
  • Convert(Type) – 如果可能,转化至一个给定的静态类型。

给了这些消息,我们还需要一些机制来让不同的类型响应这些消息。尽管DLR让开发者可以一致对待对象,而不管它们来自于静态或动态的语言,在底层,我们还是需要不同的机制来实现消息传递,分以下两种情况。

标准CLR静态类型
 
当一个对象是静态类型语言的类型定义的,这个对象的行为就完全由这个类型来描述。我们使用对象的运行时类型来确定正确的行为。例如,对GetMember消息,意味着在一个对象的类型上查找给定名字的field, property或 method,如果找到了,返回一个合适的成员,否则抛出异常。
 
DLR使用CLS(Common Language Subset)中定义的全部Attribute,来把一个对象的成员映射到一个DLR操作上。例如,我们知道add operator方法对应于add消息。另外,我们使标准对象按照我们所想的去工作,例如,所有的Delegate对象会正确的响应Call消息。
 
除了这些已经定义好的操作外,DLR加入了些额外的自定义的Attribute来有效的扩展已有的CLS操作,使得能够支持标准DLR消息的重载。一个好例子是一个静态Atrribute,使得对象能够在响应GetMember消息时重载成员查找方法,当它们在动态语言中被调用时。在现有的DLR宿主的工作中,我们找到了一些很好的场所来使用这个Attribute。一个例子是Page对象的FindControl方法。用这个Attribute,我们可以使Page能够以更自然的方法在动态语言中使用。
 
page.FindControl("text1") --> page.text1
 
事实上,在ASP .NET Page对象时,我们用一个略微更复杂的方法来重载GetMember的行为。我们不能修改真正的对象,因为我们需要运行在已有发布的ASP .NET的版本上。这意味着我们需要在外部扩展这些类型。为了完成它,我们使用了已经加到C#3和VB9中的扩展方法特性,支持LINQ.扩展方法能够像标准的名字空间那样导入,可以和类型中原有定义的方法同样使用.
 
DLR使用了扩展方法的一个稍微扩展的版本.首先,我们加入对property和operator方法的支持.其次,我们让扩展方法的作用在其他的作用域中也能调用,而C#和VB.NET只是在文件作用域中使用.例如,我们让语言能够选择应用扩展方法到所有用那种语言写的已有代码.这种方式让我们能够支持标准的Python方法于CLR类型上.例如对于字符串,Python程序员可以使用"s.title()",尽管System.String没有那个名字的方法.相同的机制使我们能够支持对象的特殊Python方法,比如使用"__class__"或"__getitem__",可以从Python代码的角度来修改类型,而不是修改类型本身.这让我们所有的语言自由的共享一个实例,并使用扩展方法时来定制不同语言的角度.
 
完全动态类型
 
对于由动态语言定义的类型,我们提供了一个更动态的方式来响应这些消息.这些动态类型实现一个特殊的接口- IDynamicObject –提供了对所有动态操作的定制处理.实现DLR上的动态语言的关键一步便是实现给定语言的标准类型的IDynamicObject接口.这就意味自IronPython在Python定义的类中实现这个接口,来支持正确的动态行为,遵守Python的多重继承和方法解析顺序.同样,基于DLR的Javascript实现这个接口来支持基于原型的继承.每一种语言完全不需要知道其它语言的类型系统的细节,只需要知道应该传递哪个正确的消息,然后依靠另外的语言正确的实现了它们那方的约定.

当前CLR一个明显的缺失就是没有这个接口的缺少标准实现.这对于那些想在DLR上实现一些标本语言而又不想要精确的匹配现有语言的语义的人是很有用的.同时对那些想要创制一般的扩展对象来消费者使用的库来说也是很有用的.我希望未来我们能够提供它,但是现在我们重点在于捕捉瑞在动态语言的精确语义,使用接口的方法来提供所需的灵活性.
 
我们还没有做到的明显的事情
 
一些明显的问题也许是不同的语言怎样使用标准的消息同时保留自己的语义.这里简单的技巧是尽管这些消息是标准的,每种语言必须去决定什么消息传递给哪部分代码.这有足够的灵活性,尽管我希望你能够想去了解更多的细节.第二个明显的问也许是上面说的这个机制听起来会相当慢,由于相当多的互操作和运行时的接口调用.这个描述试图捕捉DLR消息传递的语义-而不是实现. 这是DLR的职责使得运行快速. 我们确信今天我们已经做的很好了,而且今后我们会做的更好. 但是这一点还是需要很多解释.
 
对那些想要探索源代码的人的一些说明
 
我想要提醒那些想要深入这些代码的人最好等上几个月,因为我们的设计会活跃的重构,而且文档几乎不存在.但是,如果你想要读代码,可以看IronPython 2.0alpha1 中的Microsoft.Scripting和Microsoft.Scripting.Vestigial项目. 为了防止不明显, 使用Vestigial名字的项目名字就意味今后不会存在.标准的消息在Microsoft.Scripting.Actions名字空间中,那里"messages"被称作"Actions". IDynamicObject接口现在没有正确命名. 现在版本的这个接口将会被移走,而IActionable将会改名为IDynamicObject.现在,你应该看IActoinable.
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章