泛化關係是類元的一般描述和具體描述之間的關係,具體描述建立在一般描述的基礎之上,並對其進行了擴充套件。具體描述完全擁有一般描述的特性、成員和關係, 並且包含補充的資訊。例如,抵押是借貸中具體的一種,抵押保持了借貸的基本特性並且加入了附加的特性,如房子可以作為借貸的一種抵押品。一般描述被稱作 父,具體描述被稱作子,如借貸是父而抵押則是子。泛化在類元(類、介面、資料型別、用例、參與者、訊號等等)、包、狀態機和其他元素中使用。在類中,術語超 類和子類分別代表父和子。
泛化有兩個用途。第一個用途是用來定義下列情況:當一個變數(如引數或過程變數)被宣告承載某個給定類的值時,可使用類(或其他元素)的例項作為值,這被稱作可替代性原則(由 Barbara Liskov 提出)。該原則表明無論何時祖先被聲明瞭,則後代的一個例項可以被使用。例如,如果一個變數被宣告擁有借貸,那麼一個抵押物件就是一個合法的值。
泛化使得多型操作成為可能,即操作的實現是由它們所使用的物件的類,而不是由呼叫者確定的。這是因為一個父類可以有許多子類,每個子類都可實現定義在類整體集中的同一操作的不同變體。例如,在抵押和汽車借貸上計算利息會有所不同,它們中的每一個都是父類借貸中計算利息的變形。一個變數被宣告擁有父類,接著任 何子類的一個物件可以被使用,並且它們中的任何一個都有著自己獨特的操作。這一點特別有用,因為在不需要改變現有多型呼叫的情況下就可以加入新的類。例如,一種新的借貸可被新增加進來,而現存的用來計算利息操作的程式碼仍然可用。一個多型操作可在父類中宣告但無實現,其後代類需補充該操作的實現。這種不完整操作是抽象的(其名稱用斜體表示)。
泛化的另一個用途是在共享祖先所定義的成分的前提下允許它自身定義增加的描述,這被稱作繼承。 繼承是一種機制,透過該機制類的物件的描述從類及其祖先的宣告部分聚集起來。繼承允許描述的共享部分只被宣告一次而可以被許多類所共享,而不是在每個類中重複宣告並使用它,這種共享機制減小了模型的規模。更重要的是,它減少了為了模型的更新而必須做的改變和意外的前後定義不一致。對於其他成分,如狀態、訊號和用例,繼承透過相似的方法起作用。 每一種泛化元素都有一組繼承特性。對於任何模型元素的包括約束。對類元而言,它們同樣包括一些特性(如屬性、操作和訊號接收)和關聯中的參與者。一個子類繼承了它的所有祖先的可繼承的特性。它的完整特性包括繼承特性和直接宣告的特性。
對 類元而言,沒有具有相同特徵標記的屬性會被多次宣告,無論直接的或繼承的,否則將發生衝突,且模型形式錯誤。換而言之,祖先宣告過的屬性不能被後代再次聲 明。如果類的介面一致(具有同樣的引數、約束和含義),操作可在多個類中宣告。附加的宣告是多餘的。一個方法在層次結構中可以被多個類宣告,附在後代上的 方法替代(過載)在任何祖先中宣告過的具有相同特徵標記的方法。如果一個方法的兩個或多個副本被一個類繼承(透過不同類的多重繼承),那麼它們會發生衝突 並且模型形式錯誤(一些程式語言允許顯式選定其中的一種方法。我們發現如果在後代類中重新定義方法會更簡單、安全)。元素中的約束是元素本身及它所有祖先 的約束的聯合體,如果它們存在不一致,那麼模型形式錯誤。
在一個具體的類中,每一個繼承或宣告的操作都必須有一個已定義的方法,無論是直接定義或從祖先那裡繼承而來的。
如果一個類元有多個父類,那麼它從每一父類那裡都可得到繼承資訊(如圖 4-8 )。它的特徵(屬性、操作和訊號)是它的所有父類特徵的聯合。如果同一個類作為父類出現在多條路徑上,那麼它的每一個成員中只有它的一個複製。如果有著同 樣特徵的特性被兩個類宣告,而這兩個類不是從同一祖先那裡繼承來的(即獨立宣告),那麼宣告會發生衝突並且模型形式錯誤。因為經驗告訴我們設計者應自行解 決這個問題,所以 UML 不提供這種情形的衝突解決方案。像Eiffel 這樣的語言允許衝突被程式設計者明確地解決,這比隱式的衝突解決原則要安全,而這些原則經常使開發者大吃一驚。
泛化關係是類元的一般描述和具體描述之間的關係,具體描述建立在一般描述的基礎之上,並對其進行了擴充套件。具體描述完全擁有一般描述的特性、成員和關係, 並且包含補充的資訊。例如,抵押是借貸中具體的一種,抵押保持了借貸的基本特性並且加入了附加的特性,如房子可以作為借貸的一種抵押品。一般描述被稱作 父,具體描述被稱作子,如借貸是父而抵押則是子。泛化在類元(類、介面、資料型別、用例、參與者、訊號等等)、包、狀態機和其他元素中使用。在類中,術語超 類和子類分別代表父和子。
泛化有兩個用途。第一個用途是用來定義下列情況:當一個變數(如引數或過程變數)被宣告承載某個給定類的值時,可使用類(或其他元素)的例項作為值,這被稱作可替代性原則(由 Barbara Liskov 提出)。該原則表明無論何時祖先被聲明瞭,則後代的一個例項可以被使用。例如,如果一個變數被宣告擁有借貸,那麼一個抵押物件就是一個合法的值。
泛化使得多型操作成為可能,即操作的實現是由它們所使用的物件的類,而不是由呼叫者確定的。這是因為一個父類可以有許多子類,每個子類都可實現定義在類整體集中的同一操作的不同變體。例如,在抵押和汽車借貸上計算利息會有所不同,它們中的每一個都是父類借貸中計算利息的變形。一個變數被宣告擁有父類,接著任 何子類的一個物件可以被使用,並且它們中的任何一個都有著自己獨特的操作。這一點特別有用,因為在不需要改變現有多型呼叫的情況下就可以加入新的類。例如,一種新的借貸可被新增加進來,而現存的用來計算利息操作的程式碼仍然可用。一個多型操作可在父類中宣告但無實現,其後代類需補充該操作的實現。這種不完整操作是抽象的(其名稱用斜體表示)。
泛化的另一個用途是在共享祖先所定義的成分的前提下允許它自身定義增加的描述,這被稱作繼承。 繼承是一種機制,透過該機制類的物件的描述從類及其祖先的宣告部分聚集起來。繼承允許描述的共享部分只被宣告一次而可以被許多類所共享,而不是在每個類中重複宣告並使用它,這種共享機制減小了模型的規模。更重要的是,它減少了為了模型的更新而必須做的改變和意外的前後定義不一致。對於其他成分,如狀態、訊號和用例,繼承透過相似的方法起作用。 每一種泛化元素都有一組繼承特性。對於任何模型元素的包括約束。對類元而言,它們同樣包括一些特性(如屬性、操作和訊號接收)和關聯中的參與者。一個子類繼承了它的所有祖先的可繼承的特性。它的完整特性包括繼承特性和直接宣告的特性。
對 類元而言,沒有具有相同特徵標記的屬性會被多次宣告,無論直接的或繼承的,否則將發生衝突,且模型形式錯誤。換而言之,祖先宣告過的屬性不能被後代再次聲 明。如果類的介面一致(具有同樣的引數、約束和含義),操作可在多個類中宣告。附加的宣告是多餘的。一個方法在層次結構中可以被多個類宣告,附在後代上的 方法替代(過載)在任何祖先中宣告過的具有相同特徵標記的方法。如果一個方法的兩個或多個副本被一個類繼承(透過不同類的多重繼承),那麼它們會發生衝突 並且模型形式錯誤(一些程式語言允許顯式選定其中的一種方法。我們發現如果在後代類中重新定義方法會更簡單、安全)。元素中的約束是元素本身及它所有祖先 的約束的聯合體,如果它們存在不一致,那麼模型形式錯誤。
在一個具體的類中,每一個繼承或宣告的操作都必須有一個已定義的方法,無論是直接定義或從祖先那裡繼承而來的。
如果一個類元有多個父類,那麼它從每一父類那裡都可得到繼承資訊(如圖 4-8 )。它的特徵(屬性、操作和訊號)是它的所有父類特徵的聯合。如果同一個類作為父類出現在多條路徑上,那麼它的每一個成員中只有它的一個複製。如果有著同 樣特徵的特性被兩個類宣告,而這兩個類不是從同一祖先那裡繼承來的(即獨立宣告),那麼宣告會發生衝突並且模型形式錯誤。因為經驗告訴我們設計者應自行解 決這個問題,所以 UML 不提供這種情形的衝突解決方案。像Eiffel 這樣的語言允許衝突被程式設計者明確地解決,這比隱式的衝突解決原則要安全,而這些原則經常使開發者大吃一驚。