面向物件之繼承以及抽象(Java實現)
回顧封裝
關於面向物件三大特性,我們可以很自信的回答:封裝、繼承、多型
之前學習的封裝,可以很直觀的理解為了保護資料,我們在idea中可以用alt+insert進行一個選擇
constructer構造方法
getter和setter方法就是對封裝的一個體現,我們一般將類中的資料設為private,這樣new物件時可以防止使用者對資料進行修改,而getter和setter方法的建立就是為了進行修改和獲得資料
這樣更能體現封裝性
繼承
多個類中存在相同屬性和行為時,將這些內容抽取到單獨一個類中,那麼多個類無需再定義這些屬性和行為,只要繼承那一個類即可。
其中,多個類可以稱為子類,單獨那一個類稱為父類、超類(superclass)或者基類。
繼承描述的是事物之間的所屬關係,這種關係是: is-a 的關係。
上面的是一個基本的概述,很明顯的可以看出只要我們有一個相似的屬性,我們可以提取公共性質,形成一個父類,後面再有其他的類需要進行繼承這些屬性和方法的時候,我們就可以不需要重寫那些已經寫過的方法。
我們也可以對繼承的方法進行覆蓋重寫。具體容後再說
繼承的定義:
就是子類繼承父類的屬性和行為,使得子類物件具有與父類相同的屬性、相同的行為。子類可以直接訪問父類中的非私有的屬性和行為。
繼承的好處:
- 提高程式碼的複用性。
- 類與類之間產生了關係,是多型的前提。
繼承的格式:
class 父類 {
...
}
class 子類 extends 父類 {
...
}
我們在子類中進行一個變數的定義,如果定義父類中未曾出現的變數,這是可以嗎?
答案是可以的,子類中出現與父類不同的變數,是可以的。
子父類中出現了同名的成員變數時,在子類中需要訪問父類中非私有成員變數時,需要使用super 關鍵字,修飾父類成員變數,類似於之前學過的 this 。
使用格式:
super.父類成員變數名
Fu 類中的成員變數是非私有的,子類中可以直接訪問。若Fu 類中的成員變數私有了,子類是不能直接訪問的。通常編碼時,我們遵循封裝的原則,使用private修飾成員變數,那麼如何訪問父類的私有成員
變數呢?對!可以在父類中提供公共的getXxx方法和setXxx方法。
我們需要進行父類方法的重寫,我們應該如何去操作呢?
如果子類父類中出現重名的成員方法,這時的訪問是一種特殊情況,叫做方法重寫 (Override)。
方法重寫 :子類中出現與父類一模一樣的方法時(返回值型別,方法名和引數列表都相同),會出現覆蓋效果,也稱為重寫或者複寫。宣告不變,重新實現。
建議:在子類重寫的方法體上@override
注:
- 子類方法覆蓋父類方法,必須要保證許可權大於等於父類許可權。
- 子類方法覆蓋父類方法,返回值型別、函式名和引數列表都要一模一樣。
過載(overroad):可以不同的引數列表
關於構造方法:
- 構造方法的名字是與類名一致的。所以子類是無法繼承父類構造方法的。
- 構造方法的作用是初始化成員變數的。所以子類的初始化過程中,必須先執行父類的初始化動作。子類的構造方法中預設有一個super() ,表示呼叫父類的構造方法,父類成員變數初始化後,才可以給子類使用(super方法只能出現在構造方法的第一行)
super和this的含義
super :代表父類的儲存空間標識(可以理解為父親的引用)。
this :代表當前物件的引用(誰呼叫就代表誰)。
super和this的用法
- 訪問成員
this.成員變數 ‐‐ 本類的
super.成員變數 ‐‐ 父類的
this.成員方法名() ‐‐ 本類的
super.成員方法名() ‐‐ 父類的
- 訪問構造方法
this(...) ‐‐ 本類的構造方法
super(...) ‐‐ 父類的構造方法
子類的每個構造方法中均有預設的super(),呼叫父類的空參構造。手動呼叫父類構造會覆蓋預設的super()。super() 和 this() 都必須是在構造方法的第一行,所以不能同時出現。
繼承的特點
Java是單繼承,不是多繼承,也就是說一個類只允許有一個父親
java支援多層繼承
class A{}
class B extends A{}
class C extends B{}
最頂層的父類(祖宗)也就是object類
抽象類
父類中的方法,被它的子類們重寫,子類各自的實現都不盡相同。那麼父類的方法宣告和方法主體,只有宣告還有意義,而方法主體則沒有存在的意義了。我們把沒有方法主體的方法稱為抽象方法。Java語法規定,包含抽象方法的類就是抽象類。
定義:
- 抽象方法 : 沒有方法體的方法。
- 抽象類:包含抽象方法的類。
抽象的單詞是abstract,所以抽象的方法也用abstract進行一個修飾。
抽象方法只有方法名,沒有方法體
定義格式:
修飾符 abstract 返回值型別 方法名 (引數列表);
程式碼舉例:
public abstract void run();
抽象類
如果一個類包含抽象方法,那麼這個類必須是抽象類
定義格式:
abstract class 類名字 {
}
程式碼舉例:
public abstract class Animal {
public abstract void run();
}
繼承抽象類的子類必須重寫父類所有的抽象方法。否則,該子類也必須宣告為抽象類。最終,必須有子類實現該父類的抽象方法,否則,從最初的父類到最終的子類都不能建立物件,失去意義。
注意事項:
關於抽象類的使用,以下為語法上要注意的細節,雖然條目較多,但若理解了抽象的本質,無需死記硬背。
- 抽象類不能建立物件,如果建立,編譯無法通過而報錯。只能建立其非抽象子類的物件。
- 抽象類中,可以有構造方法,是供子類建立物件時,初始化父類成員使用的。
- 抽象類中,不一定包含抽象方法,但是有抽象方法的類必定是抽象類。
- 抽象類中,不一定包含抽象方法,但是有抽象方法的類必定是抽象類。
- 抽象類的子類,必須重寫抽象父類中所有的抽象方法,否則,編譯無法通過而報錯。除非該子類也是抽象類。
關於繼承的小案例,發紅包
這裡給出具體程式碼,加深理解,我就不進行詮釋了
Person類:
package cn.qioha.test;
public class Person {
private String name;
private int money;
public Person() {
}
public Person(String name, int money) {
this.name = name;
this.money = money;
}
public void show(){
System.out.println("my name is"+name+",money is"+money);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getMoney() {
return money;
}
public void setMoney(int money) {
this.money = money;
}
}
Manager類:
package cn.qioha.test;
import java.util.ArrayList;
public class Manager extends Person{
public Manager(String name, int money) {
super(name, money);
}
public ArrayList<Integer> send(int totalMoney,int count){
ArrayList<Integer> list = new ArrayList<>();
int money = super.getMoney();
super.setMoney(super.getMoney()-totalMoney);
if(totalMoney > money){
System.out.println("your money not enough");
return list;
}
int m = totalMoney / count;
for (int i = 0; i < count - 1; i++) {
list.add(m);
}
int n = totalMoney % count;
list.add(m+n);
return list;
}
}
Member類:
package cn.qioha.test;
import java.util.ArrayList;
import java.util.Random;
public class Member extends Person{
public Member(String name, int money) {
super(name, money);
}
public void resive(ArrayList<Integer> list){
int num = new Random().nextInt(list.size());
int money = list.remove(num);
super.setMoney(super.getMoney()+money);
}
}
demo(例項類):
package cn.qioha.test;
import java.util.ArrayList;
public class demo {
public static void main(String[] args) {
Manager ma = new Manager("peter",100);
Member q = new Member("anna",0);
Member w = new Member("nana",0);
Member e = new Member("qing",0);
ma.show();
q.show();
w.show();
e.show();
ArrayList<Integer> list = new ArrayList<>();
list = ma.send(40,3);
q.resive(list);
w.resive(list);
e.resive(list);
System.out.println("================");
ma.show();
q.show();
w.show();
e.show();
}
}
doc檔案註釋我就沒有進行一個撰寫了,因為比較的簡單,希望各位同行多多指教!