【ADT的基本概念】程序員
- 抽象數據類型(Abstract Data Type,ADT)是是指一個數學模型以及定義在該模型上的一組操做;即包括數據數據元素,數據關係以及相關的操做。
- ADT具備如下幾個能表達抽象思想的詞:
- 抽象化:用更簡單、更高級的思想省略或隱藏低級細節。
- 模塊化: 將系統劃分爲組件或模塊,每一個組件能夠設計,實施,測試,推理和重用,與系統其他部分分開使用。
- 封裝:圍繞模塊構建牆,以便模塊負責自身的內部行爲,而且系統其餘部分的錯誤不會損壞其完整性。
- 信息隱藏: 從系統其他部分隱藏模塊實現的細節,以便稍後能夠更改這些細節,而無需更改系統的其餘部分。
- 關注點分離: 一個功能只是單個模塊的責任,而不跨越多個模塊。
- 與傳統類型定義的差異:
- 傳統的類型定義:關注數據的具體表示。
- 抽象類型:強調「做用於數據上的操做」,程序員和client無需關心數據如何具體存儲的,只需設計/使用操做便可。
-
ADT是由操做定義的,與其內部如何實現無關!編程
【ADT的四種類型】編程語言
- 前置定義:mutable and immutable types
- 可變類型的對象:提供了可改變其內部數據的值的操做。Date
- 不變數據類型: 其操做不改變內部值,而是構造新的對象。String
-
- Creators(構造器):
- 建立某個類型的新對象,⼀個建立者可能會接受⼀個對象做爲參數,可是這個對象的類型不能是它建立對象對應的類型。可能實現爲構造函數或靜態函數。(一般稱爲工廠方法)
- t* -> T
- 栗子:Integer.valueOf( )
- Producers(生產器):
- 經過接受同類型的對象建立新的對象。
- T+ , t* -> T
- 栗子:String.concat( )
- Observers(觀察器):
- 獲取抽象類型的對象而後返回一個不一樣類型的對象/值。
- T+ , t* -> t
- 栗子:List.size( ) ;
- Mutators(變值器):
- 改變對象屬性的方法 ,
- 變值器一般返回void,若爲void,則必然意味着它改變了對象的某些內部狀態;固然,也可能返回非空類型
- T+ , t* -> t || T || void
- 栗子:List.add( )
- 解釋:T是ADT自己;t是其餘類型;+ 表示這個類型可能出現一次或屢次;* 表示可能出現0次或屢次。
【設計一個好的ADT】模塊化
設計好的ADT,靠「經驗法則」,提供一組操做,設計其行爲規約 spec函數
- 原則 1:設計簡潔、一致的操做。
- 最好有一些簡單的操做,它們能夠以強大的方式組合,而不是不少複雜的操做。
- 每一個操做應該有明確的目的,而且應該有一致的行爲而不是一連串的特殊狀況。
- 原則 2:要足以支持用戶對數據所作的全部操做須要,且用操做知足用戶須要的難度要低。
- 提供get()操做以得到list內部數據
- 提供size()操做獲取list的長度
- 原則 3:要麼抽象、要麼具體,不要混合 —— 要麼針對抽象設計,要麼針對具體應用的設計。
【測試ADT】性能
- 測試creators, producers, and mutators:調用observers來觀察這些 operations的結果是否知足spec;
- 測試observers: 調用creators, producers, and mutators等方法產生或改變對象,來看結果是否正確。
## OOP的基本概念
【對象】測試
- 對象是類的一個實例,有狀態和行爲。
- 例如,一條狗是一個對象,它的狀態有:顏色、名字、品種;行爲有:搖尾巴、叫、吃等。
- 概念:一個對象是一堆狀態和行爲的集合。
- 狀態是包含在對象中的數據,在Java中,它們是對象的fields。
- 行爲是對象支持的操做,在Java中,它們稱爲methods。
【類】設計
- 類是一個模板,它描述一類對象的行爲和狀態。
- 每一個對象都有一個類
- 類定義了屬性類型(type)和行爲實現(implementation)
- 簡單地說,類的方法是它的應用程序編程接口(API)。
- 類成員變量(class variable)又叫靜態變量;類方法(class method)又叫靜態方法:
- 實例變量(instance variable)和實例方法(instance method)是不用static形容的實例和方法;
- 兩者有如下的區別:
- 類方法是屬於整個類,而不屬於某個對象。
- 類方法只能訪問類成員變量(方法),不能訪問實例變量(方法),而實例方法能夠訪問類成員變量(方法)和實例變量(方法)。
- 類方法的調用能夠經過類名.類方法和對象.類方法,而實例方法只能經過對象.實例方法訪問。
- 類方法不能被覆蓋,實例方法能夠被覆蓋。
- 當類的字節碼文件被加載到內存時,類的實例方法不會被分配入口地址 當該類建立對象後,類中的實例方法才分配入口地址, 從而實例方法能夠被類建立的任何對象調用執行。
- 類方法在該類被加載到內存時,就分配了相應的入口地址。 從而類方法不只能夠被類建立的任何對象調用執行,也能夠直接經過類名調用。 類方法的入口地址直到程序退出時才被取消。
- 注意:
- 當咱們建立第一個對象時,類中的實例方法就分配了入口地址,當再建立對象時,再也不分配入口地址。
- 也就是說,方法的入口地址被全部的對象共享,當全部的對象都不存在時,方法的入口地址才被取消。
- 總結:
- 類變量和類方法與類相關聯,而且每一個類都會出現一次。 使用它們不須要建立對象。
- 實例方法和變量會在每一個類的實例中出現一次。
【接口】指針
- 概念:接口在JAVA編程語言中是一個抽象類型,用於設計和表達ADT的語言機制,其是抽象方法的集合,接口一般以interface來聲明。
- 一個類經過繼承接口的方式,從而來繼承接口的抽象方法。
- 接口並非類,編寫接口的方式和類很類似,可是它們屬於不一樣的概念。類描述對象的屬性和方法。接口則包含類要實現的方法。
- 一個接口能夠擴展其餘接口,一個類能夠實現多個接口;一個接口也能夠有多重實現
- 除非實現接口的類是抽象類,不然該類要定義接口中的全部方法。
- 接口沒法被實例化,可是能夠被實現。一個實現接口的類,必須實現接口內所描述的全部方法,不然就必須聲明爲抽象類。另外,在 Java 中,接口類型可用來聲明一個變量,他們能夠成爲一個空指針,或是被綁定在一個以此接口實現的對象。
總結:接口的好處code
-
Safe from bugs
ADT是由其操做定義的,接口就是這樣作的。
當客戶端使用接口類型時,靜態檢查確保他們只使用由接口定義的方法。
若是實現類公開其餘方法,或者更糟糕的是,具備可見的表示,客戶端不會意外地看到或依賴它們。
當咱們有一個數據類型的多個實現時,接口提供方法簽名的靜態檢查。
-
Easy to understand
客戶和維護人員確切知道在哪裏查找ADT的規約。
因爲接口不包含實例字段或實例方法的實現,所以更容易將實現的細節保留在規範以外。
-
Ready for change
經過添加實現接口的類,咱們能夠輕鬆地添加新類型的實現。
若是咱們避免使用靜態工廠方法的構造函數,客戶端將只能看到該接口。
這意味着咱們能夠切換客戶端正在使用的實現類,而無需更改其代碼。
【抽象類】
- 抽象類除了不能實例化對象以外,類的其它功能依然存在,成員變量、成員方法和構造方法的訪問方式和普通類同樣。
- 因爲抽象類不能實例化對象,因此抽象類必須被繼承,才能被使用。
- 父類包含了子類集合的常見的方法,可是因爲父類自己是抽象的,因此不能使用這些方法。
- 在Java中抽象類表示的是一種繼承關係,一個類只能繼承一個抽象類,而一個類卻能夠實現多個接口。
- 若是一個類包含抽象方法,那麼該類必須是抽象類。
- 任何子類必須重寫父類的抽象方法,或者聲明自身爲抽象類。
- 構造方法,類方法(用static修飾的方法)不能聲明爲抽象方法。
## OOP的不一樣特徵
【封裝】
- 封裝(英語:Encapsulation)是指一種將抽象性函式接口的實現細節部份包裝、隱藏起來的方法。
- 設計良好的代碼隱藏了全部的實現細節
- 乾淨地將API與實施分開
- 模塊只能經過API進行通訊
- 對彼此的內在運做不了解
- 信息封裝的好處
- 將構成系統的類分開,減小耦合
- 加快系統開發速度
- 減輕了維護的負擔
- 啓用有效的性能調整
- 增長軟件複用
- 信息隱藏接口
- 使用接口類型聲明變量
- 客戶端僅使用接口中定義的方法
- 客戶端代碼沒法直接訪問屬性
【繼承與重寫】
- 繼承概念:繼承就是子類繼承父類的特徵和行爲,使得子類對象(實例)具備父類的實例域和方法,或子類從父類繼承方法,使得子類具備父類相同的行爲。
- 重寫概念:重寫是子類對父類的容許訪問的方法的實現過程進行從新編寫, 返回值和形參都不能改變。即外殼不變,核心重寫!
- 重寫的好處在於子類能夠根據須要,定義特定於本身的行爲。 也就是說子類可以根據須要實現父類的方法。
- 實際執行時調用那種方法,在運行時決定
- 重寫方法不能拋出新的檢查異常或者比被重寫方法申明更加寬泛的異常。
- 子類只能添加新方法,沒法重寫超類中的方法。
- 當子類包含一個覆蓋超類方法的方法時,它也可使用關鍵字
super
調用超類方法。