2018-09-11
Java面向物件

比較下面向過程與面向物件
面向過程:C 語言。做一件事情的時候,“我該怎麼做?”。需要思考比較詳細的步驟,按著步驟一步步來實現。需要關心實現的每一個細節,以及資源持有的物件。
面向物件:Java 語言。做一件事情的時候,“我應該找誰來做?”。不需要我們太過關心這件事怎麼去實現,只需要指定對應的物件即可。因為物件已經具備對應的技能,指定了的物件會自己通過它的技能去實現對應的功能。
面向物件程式設計思想實際上就是一種運用物件、類、繼承、封裝、聚合、關聯、訊息、多型性等概念來構造系統的軟體開發方法。
好處:1)面向物件思維方式是一種更加符合人們日常中思考的習慣。
2)面向物件中更多的會體現出呼叫者的處理能力。
3)可以將複雜的問題,封裝起來,更加有條理去處理。
類與物件
類,用於描述多個物件的共同特徵,它是物件的模板。
物件,用於描述現實中的個體,它是類的例項。
類的定義:使用關鍵字 class 來定義 java 中的類
◆ 格式:
class 類名 {
//屬性
資料型別 變數名;
//方法
修飾符 返回值型別 方法名(引數){ }
}
類:手機。很有錢,買 iphoneX
方法:炫耀、打電話、微信、拍照、聽歌、看視訊、遊戲……
屬性:顯示屏、電池、藍芽、陀螺儀、攝像頭、擴音器……
// 定義一個類
public class 類名 {
// 定義欄位 field
int a = 1;
// 定義方法(無返回值)
public void getName(){
}
// 定義方法(有返回值)
public String getName(){
return “”;
}
}
// 類的使用:如果你要用它,必須要拿到一個類的例項。(跟Scanner、Random類一樣使用前進行例項化Scanner scan=new Scanner();...)
// 其實,就是我們需要將類放到堆記憶體中,別人才可以拿來用。
// 只要你使用一個 new 關鍵字,就可以在堆記憶體中開闢一個空間,存放類的例項。
類型別 變數名 = new 類名();
// 類型別:其實就是類名,只不過此處只是用來宣告變數的型別而已,跟外界說,當前變數的型別是和我某個類的型別一致的。
User user = new User();√√(只要是類,都這樣用)
建立物件:
◆ 格式:
類名 物件名 = new 類名();
如果要實現某些功能的話,至少要包含方法。
如果有一些固定或者變動的值需要拿來處理,則可以使用屬性進行定義。
建立物件的原理:
在例項化一個物件時,同時操作了棧記憶體和堆記憶體。
①在棧記憶體儲存物件的首地址,即引用;
②在堆記憶體中儲存了物件的屬性。
對物件的所有操作只能通過引用完成,一旦引用出棧釋放沒有任何引用指向該物件,物件就變成垃圾失效。

image
面向物件的特點------封裝,繼承,多型
概念:封裝(private 關鍵字)
封裝,把物件的屬性與方法的實現細節隱藏,僅對外提供一些公共的訪問方式
使用封裝的步驟:
1、將類的所有屬性使用關鍵字private去修飾,把它們變成私有的,不允許外部類直接訪問
2、生成或者提供公共的setter/getter方法去操作這些被隱藏起來的屬性(不再是直接對屬性進行操作了)
3、在類自己的 setter/getter方法中加入邏輯控制,以確保資料訪問的有效性和安全性
private 關鍵字,私有的意思
◆ 它可以用來修飾類中的成員(成員變數,成員方法)
◆ private 的特點:
private 修飾的成員只能在當前類中訪問,其他類中無法直接訪問
this 關鍵字
this 關鍵字,本類物件的引用
◆ this 是在方法中使用的,哪個物件呼叫了該方法,那麼,this 就代表呼叫該方法的物件引用
◆ this 什麼時候存在的?當建立物件的時候,this 存在的
◆ this 的作用:用來區別同名的成員變數與區域性變數(this.成員變數)
public void setName(String name) {
this.name = name;
}
定義一個user類、bus類,實現封裝呼叫
package com.hello.fengzhuang; public class User { //複習類的封裝 //定義類的欄位 private String name; private int age; //定義獲取名字的方法 public String getName() { return name; } //定義設定名字的方法 public void setName(String name) { this.name = name; } //定義獲取年齡的方法 public int getAge() { return age; } //定義設定年齡的方法 public void setAge(int age) { this.age = age; } //定義它自己的其他方法,這裡可以直接使用他自己的屬性 public void sitBus() { System.out.println("叫"+ name +"的那個同學坐上了388公交,"+"聽說小姐姐今年"+ age +"歲了..."); } }
另一個類
public class Bus { //複習類的封裝 //定義類的欄位以及方法 private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void run() { System.out.println("哈哈哈,你看我多快"); } public void openDoor() { System.out.println("車開門了"); } public void closeDoor() { System.out.println("車又關門了"); } public void stop() { System.out.println("哈哈哈,我要停車了"); } public void shangche(String name) { System.out.println(name+"上車了"); } }
測試類
package com.hello.fengzhuang; import org.junit.Test; public class Demo { //複習類的封裝 //呼叫這些方法 @Test public void test() { User user=new User();//使用的時候例項化User user.setName("小花"); user.setAge(20); Bus bus=new Bus();//使用的時候例項化Bus bus.run(); bus.openDoor(); bus.shangche(user.getName());//不是user.name()了,而是呼叫它的getname()方法 bus.closeDoor(); bus.stop(); user.sitBus(); } }
繼承
概念:繼承是面向物件最顯著的一個特性。繼承是從已有的類中派生出新的類,新的類能吸收已有類的資料屬性和行為,並能擴充套件新的能力。
在程式中,如果想宣告一個類繼承另一個類,需要使用 extends 關鍵字。子類又被稱為派生類; 父類又被稱為超類(Super Class)。
格式:
class 子類 extends 父類 { }
接下來通過一個案例來學習子類是如何繼承父類的,如下所示。
/* 定義員工類 Employee */ class Employee { String name; // 定義 name 屬性 // 定義員工的工作方法 public void work() { System.out.println("盡心盡力地工作"); } }
研發部員工類 Developer
/* 定義研發部員工類 Developer 繼承 員工類 Employee */ class Developer extends Employee { // 定義一個列印 name 的方法 public void printName() { System.out.println("name=" + name); } }
/* 定義測試類 */
public class Example01 { public static void main(String[] args) { Developer d = new Developer(); // 建立一個研發部員工類物件 d.name = "小明"; // 為該員工類的 name 屬性進行賦值 d.printName(); // 呼叫該員工的 printName()方法 d.work(); // 呼叫 Developer 類繼承來的 work()方法 } }
使用:直接給子類例項化
繼承的好處:
1、繼承的出現提高了程式碼的複用性,提高軟體開發效率。
2、繼承的出現讓類與類之間產生了關係,提供了多型的前提。
繼承的限制
限制一:一個子類只能夠繼承一個父類,存在單繼承侷限。
錯誤的寫法:
class A { }
class B { }
class C extends A,B { } // 一個子類繼承了兩個父類
正確的寫法:
class A {}
class B extends A {}
class C extends B {}
C實際上是屬於(孫)子類,這樣一來就相當於B類繼承了A類的全部方法,而C類又繼承了A和B類的方法,這種操作稱為多層繼承。
結論:Java之中只允許多層繼承,不允許多重繼承,Java存在單繼承侷限。
限制二:在一個子類繼承的時候,實際上會繼承父類之中的所有操作(屬性、方法),但是需要注意的是,對於所有的非私有(no private)操作屬於顯式繼承(可以直接利用物件操作),而所有的私有操作屬於隱式繼承(間接完成set get)。
限制三:在繼承關係之中,例項化的是子類物件,但是發現它會預設先執行父類建構函式(方法),呼叫父類構造的方法體執行,而後再例項化子類物件,呼叫子類的構造方法。而這個時候,對於子類的構造而言,就相當於隱含了一個super()的形式.
!!!super呼叫父類構造時,一定要放在構造方法的首行上。
繼承-子父類中成員變數的特點
當子父類中出現了同名成員變數時,在子類中若要訪問父類中的成員變數,必須使用關鍵字 super
來完成。super 用來表示當前物件中包含的父類物件空間的引用
在子類中,訪問父類中的成員變數格式:
super.父類中的成員變數
繼承-子父類中成員方法特點-重寫&應用
①子父類中成員方法的特點
當在程式中通過物件呼叫方法時,會先在子類中查詢有沒有對應的方法,若子類中存在就會執行子類中的方法,若子類中不存在就會執行父類中相應的方法。
看如下程式碼:
class Fu{ public void show(){ System.out.println("Fu 類中的 show 方法執行"); } }
繼承
class Zi extends Fu{ public void show2(){ System.out.println("Zi 類中的 show2 方法執行"); } }
測試
public class Test{ public static void main(String[] args) { Zi z = new Zi(); z.show(); //**子類中沒有 show 方法,但是可以找到父類方法去執行** z.show2(); } }
成員方法特殊情況——覆蓋
子類中出現與父類 一模一樣的 方法時,會出現覆蓋操作, 也稱為 override 重寫、複寫或者覆蓋。
舉例:比如手機,當描述一個手機時,它具有發簡訊,打電話,顯示來電號碼功能,後期由於手機
需要在來電顯示功能中增加顯示姓名和頭像,這時可以重新定義一個類描述智慧手機,並繼承原有描述
手機的類。並在新定義的類中覆蓋來電顯示功能,在其中增加顯示姓名和頭像功能。
//手機類
class Phone{ public void sendMessage(){ System.out.println("發簡訊"); } public void call(){ System.out.println("打電話"); } public void showNum(){ System.out.println("來電顯示號碼"); } }
//智慧手機類
class NewPhone extends Phone{ //覆蓋父類的來電顯示號碼功能,並增加自己的顯示姓名和圖片功能 public void showNum(){ //呼叫父類已經存在的功能使用 super super.showNum(); //增加自己特有顯示姓名和圖片功能 System.out.println("顯示來電姓名"); System.out.println("顯示頭像"); } }
重寫需要注意的細節問題:
①子類方法覆蓋父類方法,必須要保證許可權大於等於父類許可權。
② 寫法上稍微注意:必須一模一樣:方法的返回值型別 方法名 引數列表都要一樣。