科技愛好者週刊(第 128 期):這個社會是否正在變成“賽博朋克”?
面向物件
面向過程 & 面向物件
-
面向過程思想
- 步驟清晰簡單,第一步做什麼,第二步做什麼
- 面對過程適合處理一些較為簡單的問題
-
面向物件思想
- 物以類聚,分類的思想模式,思考問題首先解決問題需要哪些分類,然後對這些分類進行單獨思考。最後,才對某個分類下的細節進行面向過程的思索
- 面向物件適合處理複雜的問題,適合處理需要多人合作的問題
-
對於描述複雜的事物,為了從巨集觀上把握、從整體上合理分析,我們需要使用面向物件的思路來分析整個系統。但具體到微操作,仍然需要面向過程的思路去處理
什麼是面向物件
- 面向物件程式設計(Object-Oriented Program)
- 面向物件程式設計的本質就是:以類的方式組織程式碼,以物件的組織(封裝)資料
- 抽象
- 三大特性:
- 封裝
- 繼承
- 多型
- 從認識論角度考慮,是先有物件後有類。物件,是具體的事物。類,是抽象的,是對物件的抽象
- 從程式碼執行角度考慮,是先有類後有物件。類是物件的模版
類與物件的關係
- 類是一種抽象的資料型別,它對某一類事物整體描述定義,但不能代表某一個具體事物
- 動物,植物,手機,電腦
- Person類、Pet類等等,這些類都是用來描述和定義某一類事物應該具有的屬性、特點、行為
- 物件是抽象概念的具體例項
- 張三就是人的一個具體例項
- 能夠體現出特點,展現出功能的是具體的例項,而不是一個抽象概念
建立和初始化物件
-
使用
new
關鍵字建立物件 -
使用
new
關鍵字建立物件時,除了分配記憶體空間之外,還會對建立好的物件進行預設的初始化以及對類中構造器的呼叫 -
類中的構造器(constructor)也稱為構造方法,是在進行建立物件時必須要呼叫的。並且構造器有以下兩個特點:
- 必須和類的名字相同
- 必須沒有返回型別,也不能寫void
-
new
的本質就是在呼叫構造器 -
構造器的作用:初始化物件的屬性
-
注意:
- 定義有參構造之後,如果想使用無參構造,就要顯示的定義一個無參構造
- 快捷鍵:alt+insert;Mac:control+return
面向物件的三大特性之封裝
該露的露,該藏的藏
- 程式設計要追求“”高內聚,低耦合“。高內聚就是類的內部資料操作細節自己完成,不想允許外部干涉;低耦合就是僅暴露少量的方法給外部使用
封裝(資料的)
- 通常,應禁止直接訪問一個物件中的資料的直接表示,而應該通過操作介面來訪問,這稱為資訊隱藏
- 屬性私有,get/set
面向物件的三大特性之繼承
-
繼承的本質是對某一批類的抽象,從而實現對現實世界更好的建模
-
extends
表子類是父類的擴充套件 -
Java中類只有單繼承,沒有多繼承
-
繼承是類和類之間的關係。除此之外,類和類之間的關係還有依賴,組合,聚合等
-
繼承關係的兩個類,一個是子類一個是父類,子類繼承父類,用關鍵詞
extends
表示 -
子類和父類之前,從意義上講存在“is a“的關係
-
object類,在Java中,所有的類,都預設繼承object類
-
super(對比 this)
- 呼叫父類的構造方法,必須在構造方法第一行
- 必須只能出現在子類的方法或構造方法中
- super和this不能同時呼叫構造方法
-
vs this
代表的物件不同
- this:本身呼叫者這個物件
- super:代表父類物件
前提
- this沒有繼承也可以使用
- super只能在繼承條件下才可以使用
構造方法
- this(); 子類的構造方法
- super(); 父類的構造方法
面向物件的三大特性之多型
方法重寫
-
需要有繼承關係,子類重寫父類的方法
-
方法名必須相同
-
引數列表必須相同
-
修飾符:範圍可以擴大,不能縮小:public > protected > default > private
-
丟擲異常:可以被縮小,但不能擴大: ClassNotFoundException --> Exception(大)
-
子類的方法必須要和父類的一致,方法體不同
-
為什麼要重寫
- 父類的功能子類不一定需要,或者不一定滿足需求
-
不能重寫的情況:
- static 屬於類,不屬於例項
- final 常量
- private
-
control+return(Mac),override
多型
-
動態編譯:型別:可擴充套件性
-
即同一方法可以根據傳送物件的不同而採用多種不同的行為方式
-
一個物件的實際型別是確定的,但可以指向物件的引用的型別可以有很多
-
多型存在的條件
- 有繼承關係
- 子類重寫父類方法
- 父類引用指向子類物件
-
多型是方法的多型,屬性沒有指向性
-
instanceof
Student s1 = new Student(); Person s2 = new Student();// 父類的引用指向子類 Object s3 = new Student(); //Object > String //Object > Person > Student //Object > Person > Teacher //System.out.println(x instanceof y);// 能否編譯通過取決於,x和y之間是否存在父子關係 System.out.println(s3 instanceof Student); // true System.out.println(s3 instanceof Person); // true System.out.println(s3 instanceof Object); // true System.out.println(s3 instanceof Teacher); // false System.out.println(s3 instanceof String); // false System.out.println("========================="); System.out.println(s2 instanceof Student); // true System.out.println(s2 instanceof Person); // true System.out.println(s2 instanceof Object); // true System.out.println(s2 instanceof Teacher); // false System.out.println(s2 instanceof String); // 編譯報錯! System.out.println("========================="); System.out.println(s1 instanceof Student); // true System.out.println(s1 instanceof Person); // true System.out.println(s1 instanceof Object); // true System.out.println(s1 instanceof Teacher); // 編譯錯誤! System.out.println(s1 instanceof String); // 編譯報錯!
-
型別轉換
- 把子類轉換為父類,向上轉型
- 把父類轉換為子類,向下轉型,強制轉換
- 方便方法的呼叫,減少重複的程式碼