第一章 什么是物件
1.1 抽象的歷程
”物件“:問題空間中的元素及其解決方案空間中的具體呈現,
理念即是通過添加各種新的物件,可以將程式改編為一種描述問題的語言,
物件是具有狀態、行為及標識的,
物件可以擁有自己的內部資料(用以賦予狀態),方法(用以產生行為),物件在記憶體中都有唯一的地址,
1.2 物件具有介面
關鍵字class的由來:狀態不同但結構相同的物件匯聚在一起而組成的同一類物件,
類是描述了一系列具有相同特征(即資料元素)和行為(即功能方法)的物件,也就是說類其實是資料型別,
在面向物件領域中,我們將創建的變數稱為”物件“或者”實體“,將操作變數稱為”發送訊息“或者”發送請求“,
讓一個物件真正的發揮其作用就是向物件發送請求,而物件能夠接收什么請求,是由其介面決定,物件所歸屬的類則定義了這些介面,
eg:
| 型別名 | Light |
|---|---|
| 介面 | on() |
| off() | |
| brighten() | |
| dim() |
Light lt=new Light();
lt.on();
介面定義了能向這個物件發送的請求,
代碼+隱藏的資料=”實作“
1.3 物件可以提供服務
在開發一個面向物件程式或者理解其設計時,可以將物件想象成”服務提供者“,程式是為用戶提供服務的,
高內聚性:設計的組件(比如物件、方法、物件庫等)無論從哪個方面都整合的很好,
1.4 隱藏的實作
程式員的兩大陣營:”類的創建者“(負責創建新資料型別的人),”客戶程式員“(在自己的應用程式里使用現有資料型別的人),
”類的創建者“:只暴露必要的介面給客戶程式員,同時隱藏其他所有不必要的資訊,這樣可以避免修改隱藏資訊時對其他人造成的影響,即是隱藏代碼的具體實作可以有效的減少程式的bug,
設定訪問控制
首要原因:防止客戶程式員接觸本不應該接觸的資料型別內部運轉的代碼(即非那些用于解決特定問題的介面部分),
第二個原因:讓介面部分和實作部分分離,便于庫的設計者在改變類的內部作業機制時,不用擔心影響到使用該類的客戶程式員,
Java提供了三個顯示的關鍵字(訪問修飾符)來設定訪問控制:
- public:可被所有人訪問
- private:只能被類的創建者通過該類自身的方法訪問
- protected:與private相似,但繼承的子類可以訪問protected成員
還有一種默認的訪問權限,即是包訪問(package access)
1.5 復用實作
復用一個類的最簡單方法就是直接使用該類所生成的物件,
組合:新創建的類可以由任意數量和型別的物件組成,也可以任意組合這些物件以滿足想要的功能,即是利用已有的類組合成一個新的類,(如果組合是動態的,通常稱為聚合)
1.6 繼承
為了避免重復性代碼的書寫(即創建功能相近的類),我們復制了現有的類并且能夠在此基礎上再做一些增補,這就是繼承的好處,
子類可繼承父類的所有成員變數和方法及介面,同時子類可以增加或者復寫父類沒有或者已有的成員變數和方法及介面,
區分子類和父類很簡單,第一種直接為子類添加新的方法,那么執行時,父類的行為講會和你的預期不符,第二種就是重寫方法,可以讓子類與父類增加差異化,
is-a關系與is-like-a關系
替換原則(里氏替換原則):即當只重寫父類中定義的方法時,子類和父類的型別將會是完全相同的(介面一模一樣),這樣我們就能夠用子類的物件代替父類的物件,這是一種理想的繼承方式,即是is-a關系,
當我們為子類的介面添加新的內容時,子類依然能夠代替父類的物件,但不餓能通過父類的介面獲取子類的新方法,這種關系即是is-like-a關系,
1.7 多型
當涉及型別層次的時候,將一個物件視為父類的一個實體,而不是物件實際的類,
不同子類執行父類的同一方法時的結果應該是不同的,那么我們可能需要的是派生子類,這樣可以擴展程式設計的能力,
eg:
當Bird物件的move()方法被呼叫時,(Goose物件執行的是行走、飛翔或者游泳,Penguin物件執行的則是移動或者游泳),
我們將子類視為父類從而能夠區別不同物件的不同方法,這也是向上轉型,
前期系結是非面向物件編譯器的呼叫函式時所觸發的,這樣意味著當呼叫具體方法時,該方法名就決定了被執行代碼的絕對地址,
但對于繼承,程式需要運行時才能明確代碼的地址,所以就有了面向物件使用的機制:后期系結,(Java里會默認具備動態系結特性,所以不用借助其他的關鍵字或者代碼來實作多型,但c++會使用virtual關鍵字)
1.8 單根層次結構
單根層次結構有利于實作垃圾收集器,這也是Java相對于c++的一個重要改進,既然所有的物件都擁有型別資訊,那么就不用再去了解某個物件具體是什么型別了,這個特性對于系統級別的操作尤其重要,比如例外處理,
1.9 集合
在大多數語言中,用陣列就可以保存許多的內容,而Java中通常是創建一種新型別的物件,然后利用這個新物件來保存其他物件的參考,這個物件通常被叫做集合,并且會根據放入其中的內容而自行調整空間,
當然不同的集合也有著不同的用途:
幾個不同的List類(用于保存序列),幾個Map類(也叫做關聯陣列,用于關聯物件),幾個Set類(用于保存不同型別的物件),以及一些佇列(queue)、樹(tree)、堆疊(stack)等,
不同的集合在特定操作的執行效率上也有差異,比如:ArraytList和LinkedList,ArraytList隨機獲取元素是一種耗費固定時間的操作,意思就是不管你選擇獲取哪個元素,耗費的時間都是相同的,而LinkedList在串列中隨機選擇元素是一種代價很大的操作,查找串列更深處的元素也會耗費更多的時間,如果要在串列中插入元素,LinkedList耗費的時間會比ArrayList更少,
引數化型別(泛型)
當我們知道向上轉型是安全的時,反過來我們不知道Object物件實際上是什么型別,那么這種向下轉型就是不安全的,當然如果向下轉型失敗,會得到例外,
為了節省向下轉型與其關聯的運行檢查所需要的時間,我們通常關注創建的集合能不能明確所包含的物件型別,
1.10 物件的創建和生命周期
C++需要顯式洗掉物件,因為C++的宗旨是效率優先,
Java只允許動態分配記憶體,當創建一個物件時,需要new運算子來創建一個物件的動態實體,
Java語言的底層支持垃圾收集器機制,所以它會自動找到無用的物件并將其銷毀,
1.11 例外處理
例外是從錯誤發生之處“拋出”的物件,而根據錯誤型別,它可以被對于的例外處理程式所“捕獲”,當然例外不允許被忽略,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/500411.html
標籤:其他
上一篇:記憶中的香河肉餅
下一篇:描述性統計
