一個真實的對象(第二部分)

本文翻譯自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.
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章