Stories

Detail Return Return

UML之泛化、特化和繼承 - Stories Detail

在UML(統一建模語言)中,泛化(Generalization)和特化(Specialization)是面向對象思想中繼承(Inheritance)關係的重要概念,它們描述類與類(或用例與用例、參與者與參與者等)之間的一般與特殊的關係。
泛化是一種表示類之間繼承關係的方式,它指定了子類如何特化超類(父類)的所有特徵和行為。在UML中,泛化關係通過帶空心三角箭頭的實線表示,箭頭指向超類。這種關係表明,子類是一種特殊的超類,它繼承了超類的所有屬性、操作(方法)以及與其他類的關係,並且可能添加新的屬性、操作或改變超類某些行為的具體實現。泛化關係支持代碼重用和多態,是實現軟件設計複用性和靈活性的重要手段。
特化是泛化的逆過程,即從一般到特殊的過程。雖然UML中更常用“泛化”來描述這種關係,但“特化”一詞在面向對象編程和UML的語境下,也常被用來描述子類如何成為超類的一個特定版本或實現。特化意味着子類不僅繼承了超類的所有屬性和操作,還可能對這些屬性和操作進行特定的實現或限制,以滿足特定的需求。特化是面向對象編程中實現多態性和代碼複用的基礎之一。
簡而言之,泛化和特化是同一繼承關係的兩個不同視角:泛化沿空心三角箭頭向上移動,它從父類的角度描述子類如何成為其特殊化版本,而特化則沿空心三角箭頭向下移動,它從子類的角度描述其如何特化或具體化父類的屬性和行為。這兩個概念在UML中用於清晰地表示類之間的繼承關係,促進軟件設計的複用性和可維護性。
當然,泛化和特化這種繼承關係不只可以用於描述類的關係,也可以應用於用例、參與者等UML元素。
下圖使用繼承關係描述了UML中不同圖之間的關係。

在上圖中,對其頂層關係可以做出如下解讀:
·結構圖(Structure Diagram)是一種圖(Diagram)。
·結構圖(Structure Diagram)是圖(Diagram)的一種(或某類圖)。
·結構圖(Structure Diagram)是圖(Diagram)的一種特化。
·圖(Diagram)是結構圖(Structure Diagram)的泛化。
·結構圖(Structure Diagram)和行為圖(Behavior Diagram)是圖(Diagram)的子類型。
·圖(Diagram)是結構圖(Structure Diagram)和行為圖(Behavior Diagram)的父類型。
特化關係允許子類替代超類,為了實現替代,超類上所有可用的特性(屬性、操作、約束、信號、接收和關聯)也必須在子類上可用。
在UML圖中描述這種繼承關係時,可以讓所有子類在超類側共享一個空心三角形,令其整體呈樹狀結構。當然,也完全可以讓每個子類在超類側使用自己獨有的空心三角形。並且空心三角的位置只要是指向並緊貼對應的超類即可,其與超類的接觸點及方向可以是任意的,我們可以基於佈局需要和美觀因素進行選擇與調整。
下圖展示了繼承關係中的一些細節,通過閲讀這張圖我們可以瞭解繼承是如何進行工作的。

注:在UML中如果類名是斜體,如圖中的“Borrowable Material”則表示該類是一個抽象類。
超類“可借閲材料(Borrowable Material)”的特性,包含屬性編號(number)、標題(title)及操作借閲(borrow()),被所有子類繼承,即它們在所有子類上都是可用的。
子類“音頻CD(Audio CD)”和“書籍(Book)”的類圖描述中,上述屬性編號(number)、標題(title)被重複描述了。UML建議使用插入符號(^)標記繼承的特性,子類“音頻CD(Audio CD)”遵循這個規則在屬性number和title前添加了“^”符號表明這兩個屬性是繼承自超類。但並非所有UML工具都遵循了這一建議,例如Enterprise Architect,它將屬性列表按所屬類進行分段,源自超類的屬性它將使用“::超類名”進行命名空間標註,正如圖中子類“書籍(Book)”那樣,超類的屬性number和title被展示在了“::Borrowable Material”之下的區域;而Visual Paradigm則在表示時不區分該特性是繼承自超類還是當前類所特有的。
實際上,在描繪UML圖形時,並不需要描畫所有繼承自超類的特性,例如上圖中在超類“可借閲材料(Borrowable Material)”中的操作借閲borrow()在兩個子類(Audio CD和Book)中均未展示,但子類確實會繼承借閲borrow()這個操作。
在子類Audio CD中我們添加了另外一個新的屬性ISRC,在子類Book中我們也添加了新的屬性ISBN。這使得這兩個子類均擁有三個屬性,其中兩個繼承自它們的超類Borrowable Material,另外一個是這兩個子類所特有的屬性。
類Juvenile Book和類Adult Book均繼承自類Book。它們又各自添加了一條自己特有屬性,而繼承自超類的屬性類Juvenile Book採用了在屬性前添加插入符號(^)的形式進行説明,此時,只能通過這個符號表明屬性是繼承自超類,而具體是繼承自類Book還是Borrowable Material並沒有辦法進行區分;類Adult Book在表示屬性時由於採用了命名空間的方式,它則可以明確地表明繼承的屬性來自哪個超類。
對於類Book,在圖中還通過關聯的方式與類Person建立關係,在關聯的末端的“+author”表明在類Book中還有一個多重性為任意、有序的、類型為Person、名為author的屬性;類似的,類Peron也有一個多重性為任意、類型為Book的名為myBook的屬性。
對於類Book的子類Juvenile Book與Adult Book,上述類Book與類Person的關聯關係也會由於存在繼承關係而自動擁有。不過需要特別注意的是,子類Juvenile Book與Adult Book從關聯中會繼承角色名稱author(作為屬性author),而myBook是存在於類Person中的角色名稱,它並不會產生任何繼承關係。子類Juvenile Book採用在屬性區域描畫的方式展示了它繼承於關聯的角色名稱author;而子類Adult Book則通過添加與類Person關聯的方式展示它繼承於關聯的角色名稱author,並且,它更改了它在類Person中的對應的角色名稱(屬性名稱)。
當在一個子類中請求一個特性時,它會檢索該特性的定義。如果在當前子類中找不到該特性的定義,它就會檢索該子類的直接超類(父類),如果依然沒有找到,則繼續向上層超類檢索,直到找到最近的該特性的定義為止。如果檢索到超類鏈的頂端也未找到該特性的定義,UML規範並未説明這會發生什麼,通常這是實現或者説編程語言層面的問題。
注:在具體的編程語言中,可能會面臨更加複雜情況,例如在一個子類中定義與超類完全相同的屬性與操作,而在實例化時,又通過超類類型的變量名指向一個子類的實例。此時,通過這個變量訪問屬性與操作將變得更加難以理解。
通過繼承關係與其他關係結合,可以精確描述更為複雜的場景。例如繼承關係與組合關係一起使用,可以描述複雜結構的構成。例如一個系統中包含有兩種類型的結構:簡單結構和複合結構。簡單結構是單一結構,而複合結構由多個結構構成,這些結構既可以是簡單結構也可以是複合結構。基於此,我們可以用下圖來描述這個結構的關係。

在圖中簡單結構(Simple Structure)和複合結構(Compound Structure)這兩者均繼承於不能實例化的(抽象)結構(Structure);抽象結構與複合結構之間存在組合關係,一個複合結構可能包含有任意多個結構,而這個結構要麼是簡單結構要麼是複合結構。

user avatar buguge Avatar
Favorites 1 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.