程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> 面向對象語言概論(四)

面向對象語言概論(四)

編輯:關於C++

四,徹底劃清界限(繼續分離Subclassing和Subtyping)

在第二節我們討論了部分分離Subclassing和subtyping的方法,即subclassing-implies-subtyping. 現今的許多面向對象語言,如Java, C#都是采用了這種技術。除此之外,還有一種進一步分離Subclassing和subtyping的方法。這種被稱作inheritance-is-not-subtyping的方法通過完全割裂subclassing和subtyping之間的聯系而在更大程度上方便了代碼的重用。

它的產生很大程度上是由於人們想要使用在反協變位置上的Self類型 (如Self類型的參數)。當然,增大繼承的能力的代價是subsumption的靈活性降低了。當Self類型出現在反協變的位置上時,subclass不再意味著subtype, 因此,subsumption也就不存在了。

下面請考慮這樣兩個類型:

ObjectType Max is

var n: Integer;

method max(other:Max): Max;

end;

ObjectType MinMax is

var n: Integer;

method max(other:MinMax): MinMax;

method min(other:MinMax): MinMax;

end;

再考慮兩個類:

class MaxClass is

var n:Integer :=0;

method max(other: Self): Self is

if self.n > other.n then return self else return other end;

end;

end;

subclass MinMaxClass of MaxClass is

method min(other: Self): Self is

if self.n < other.n then return self else return other end;

end;

end;

方法min和max是二元的,因為它操作兩個對象:self和other. other的類型是一個出現在反協變位置上的Self類型。

注意,方法max有一個反協變的參數類型Self, 並且它被從類MaxClass繼承到了MinMaxClass.

很直觀地,類MaxClass對應著類型Max;類MinMaxClass對應著類型MinMax. 為了精確地表示這種對應關系,我們必須針對包含使用Self類型的成員的類重新定義ObjectTypeOf,以便得到ObjectTypeOf(MaxClass) = Max, ObjectTypeOf(MinMaxClass) = MinMax。

為了使以上的等式成立,我們把類中的Self類型映射到ObjectType中的類型名稱本身。我們同時讓Self類型在繼承的時候特化。

在本例中,當我們映射MinMaxClass的類型時,我們把繼承來的max方法中的Self類型映射到MinMax類型。而對MaxClass中max方法的Self類型,我們使用Max類型。

如此,我們可以得到,任何MaxClass生成的對象,都具備Max類型。而任何MinMaxClass生成的對象都具備MinMax類型。

雖然MinMaxClass是MaxClass的子類,但這裡MinMax卻不是Max的子類型(subtype).

舉個例子,如果我們假設subtype在這種情況下成立,那麼,對以下的這個類:

subclass MinMaxClass’ of MinMaxClass is

override max(other: Self): Self is

if other.min(self) = other then return self else return other end;

end;

end;

根據我們對Self類型的映射規則和基於結構的subtype規則,我們知道,ObjectTypeOf(MinMaxClass’) = MinMax, 所以,對任何MinMaxClass’生成的對象mm’ ,我們可以知道mm’ : MinMax.

而如果MinMax <: Max成立,根據subsumption, 我們就能推出mm’ : Max.

於是當我們調用mm’.max(m)的時候,m可以是任何Max類型的對象。但是,當max的方法體調用other.min(self)的時候,如果這個other不具有min方法,這個方法就會失敗。

由此可見,MinMax <: Max並不成立。

子類(subclass) 在使用反協變的Self類型時就不再具有subtype的性質了。

五,對象協議 (Object Protocol)

從上一節的討論,我們看到對使用反協變Self類型的類,subclass不再是subtype了。這是一個令人失望的結果,畢竟很多激動人心的面向對象的優點是通過subtype, subsumption來實現的。

不過,幸運的是,雖然失去了subtype, 我們還是可以從中挖掘出來一些可以作為補償的有用的東西的。只不過,不象subtype, 我們不能享受subsumption了。

下面就讓我們來研究這種新的關系。

在第四節的MinMax的例子中,subtype不再成立;簡單地使用泛型,引入

ObjectOperator P[M <: Max] is … end; 也似乎沒有什麼用。P[Max]雖然成立,但P[MinMax]卻是不合法的,因為MinMax <: Max不成立。

但是,直觀上看,任何支持MinMax這種協議的對象,也支持Max協議的 (雖然我們還不知道這個“協議”到底是個什麼東西)。於是,似乎隱隱約約地又一個叫做“子協議”(subprotocol)的家伙在向我們招手了。

為了發現這個子協議的關系,讓我們先定義兩個type operator (還記得嗎?就是作用在類型上的函數):

ObjectOperator MaxProtocol[X] is

var n: Integer;

method max(other: X) :X;

end;

ObjectOperator MinMaxProtocol[X] is

var n:Integer;

method max(other: X):X;

method min(other: X):X;

end;

這樣,Max = MaxProtocol[Max], MinMax = MinMaxProtocol[MinMax]

更一般地說,我們可以定義:

什麼 = 什麼-Protocol[什麼]

還記得lamda-calculus裡的fixpoint嗎?給定一個函數F, F(fixpoint(F)) = fixpoint(F)

而在我們這個子協議的type operator裡,如果我們認為type operator是作用於類型的函數的話, 那麼這個“什麼”,就是“什麼-Protocol”函數的fixpoint啊!

也就是說:

什麼= fixpoint (什麼-Protocol).

除了以上的fixpoint的性質,我們還發現了存在於Max和MinMax之間的關系。

首先,MinMax是MaxProtocol的一個post-fixpoint,即:

MinMax <: MaxProtocol[MinMax]

其次,我們可以看出:

MinMaxProtocol[Max] <: MaxProtocol[Max]

MinMaxProtocol[MinMax] <: MaxProtocol[MinMax]

最後,如果我們用<::來表示一個更高階的子類型關系:

P <:: P’ 當且僅當 P[T] <: P’[T] 

那麼,MinMaxProtocol <:: MaxProtocol.

對於子協議的定義,我們可以采取上面的<::的定義,即:

如果S-Protocol<::T-Protocol, 那麼我們稱類型S和類型T之間是子協議關系。 (1)

我們也可以不用這個高階的關系,仍然使用<:這個subtype的關系:

如果S<:T-Protocol[S], 那麼我們稱類型S和類型T之間是子協議關系。 (2)

其實,第一個定義似乎更直觀一點,它更明確地顯示出子協議關系是作用於類型上的函數(type operator)之間的關系,而不是類型之間的關系。

使用泛型技術,如果我們的某一個類型需要一個實現MaxProtocol的類型來實例化的話,我們可以采用下面兩種方法中的一種:

ObjectOperator P1[X <: MaxProtocol[X]] is … end; (1)

ObjectOperator P2[P <:: MaxProtocol] is … end; (2)

這兩種方法在表達能力上是相同的。第一種方法叫做F-bounded parameterization. (譯者按,Generic Java據說就采用了這個方法);第二種方法叫做 higher-order bounded parameterization.

對於具體語言的實現,為了方便,我們可以隱藏這個type operator. 語法上可以直接對類型支持subprotocol的關系(用<#來表示)。

對我們的MinMax的例子來說,我們就有:

MinMax <# Max.

(譯者按,繞了一大圈,什麼fixpoint啊,post-fixpoint啊,什麼高階關系啦,希望沒把你繞暈。其實,你只需要記住MinMax <# Max, 就八九不離十了,呵呵)

<#這個關系並不具有subsumption的性質,所以,你不能指望從它身上得到傳統OO裡面的多態。但是,與泛型相結合,它卻是非常有用的。

比如說,我們可以對我們的所有你用來當作參數傳給我的基於GP的快速排序模板函數給出這樣的約束:用來實例化這個模板函數的的類型必須支持Comparable協議。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved