9.類型一致
大多數語言都有基本類型(int、long等等)。高級類型最終是由基本類型構成的。能以同樣的方式處理基本類型和高級類型通常來說是有用處的。例如,如果集合可以象包容sting那樣包容int是有用的。為此,Smalltalk通過犧牲些許效率象處理string或Form一樣來處理int和long。Java試圖避免這個效率損失,它象C和C++那樣處理基本類型,但又為每一個基本類型提供了相應的包裝類—int包裝為Integer,double包裝為Double。C++模板參數可接受任何類型,只要該類型提供了模板定義的操作的實現。
【譯注:在Java中,你可以這麼寫:
int i = 1;
double d = 1.1;
Integer iObj = new Integer(1);
Double dObj = new Double(1.1);
以下寫法是錯誤的:
int I = new int(1);
Integer iObj = 1;
】
C#對該問題提供了一個不同的解決方案。在上一節裡,我介紹了C#中的結構,指出基本類型不過是結構的一個別名而已。既然結構擁有所有對象類型擁有的方法,那代碼就可以這麼寫:
int i = 5;
System.Console.WriteLine (i.ToString());
如果我們想象使用一個對象那樣使用一個結構,C#將為你裝箱該結構為對象,當你再次需要使用結構時,可以通過拆箱實現:
Stack stack = new Stack ();
stack.Push (i); // 裝箱
int j = (int) stack.Pop(); file://拆箱
拆箱不僅是類型轉換的需要,它也是一個無縫處理結構和類之間關系的方式。你要清楚裝箱是做了創建包裝類的工作,盡管CLR可以為被裝箱的對象提供附加的優化。
【譯注:可以這麼認為,在C#中,對於任何值(結構)類型,都存在如下的包裝類:
class T_Box file://T代表任何值類型
{
T Value;
T_Box(T t){Value = t;}
}
當裝箱時,比如:
int n = 1;
object box = n;
概念上相當於:
int n = 1;
object box = new int_Box(i);
當拆箱時,比如:
object box = 1;
int n = (int)box;
概念上相當於:
object box = new int_Box(1);
int n = ((int_Box)box).Value;】
【作者注:C#的設計者在設計過程中應該考慮過模板。我懷疑未采用模板有兩個原因:第一個是混亂,模板可能很難和面向對象的特性融合在一起,它為程序員的帶來了太多的(混亂)設計可能性,而且它很難和反射一起工作;第二點是,如果.NET庫(例如集合類)沒有使用模板的話,模板將不會太有用。不過,果真.NET類使用了它們,那將有20多種使用.NET類的語言不得不也要能和模板一起工作,這在技術上是非常難以實現的。
注意到模板(泛型)已經被Java社團考慮納入Java語言規范之中是一件有意思的事。或許每個公司都會各唱各的調—Sun說“.NET患了最小公分母綜合症”,而微軟則說“Java不支持多語言”。
(8月10日致歉)看了一個對Anders Hejlsberg的專訪後(http://windows.oreilly.com/news/hejlsberg_0800.html),感覺似乎模板已浮出地平線,但第一版沒有,正因我們上面提到的種種困難。看到IL規范是如此寫法使得IL碼可以展現模板(用一個非破壞的方式以讓反射可以很好的工作)而字節碼則不可以是一件很有趣的事。在此,我還給出了一個關於Java社團考慮要加入泛型的鏈接:http://jcp.org/jsr/detail/014.jsp 】
【譯注:此處是上文提到的對Anders Hejlsberg采訪的中文版鏈接:http://www.csdn.net/develop/article/11/11580.shtm。另外,如欲了解更多關於泛型編程知識,請參見此處鏈接:http://www.csdn.net/develop/article/11/11440.shtm】