1. 程式人生 > 實用技巧 >面向物件之繼承以及抽象(Java實現)

面向物件之繼承以及抽象(Java實現)

回顧封裝

關於面向物件三大特性,我們可以很自信的回答:封裝、繼承、多型

之前學習的封裝,可以很直觀的理解為了保護資料,我們在idea中可以用alt+insert進行一個選擇



constructer構造方法

getter和setter方法就是對封裝的一個體現,我們一般將類中的資料設為private,這樣new物件時可以防止使用者對資料進行修改,而getter和setter方法的建立就是為了進行修改和獲得資料

這樣更能體現封裝性

繼承

多個類中存在相同屬性和行為時,將這些內容抽取到單獨一個類中,那麼多個類無需再定義這些屬性和行為,只要繼承那一個類即可。

其中,多個類可以稱為子類,單獨那一個類稱為父類、超類(superclass)或者基類。


繼承描述的是事物之間的所屬關係,這種關係是: is-a 的關係。

上面的是一個基本的概述,很明顯的可以看出只要我們有一個相似的屬性,我們可以提取公共性質,形成一個父類,後面再有其他的類需要進行繼承這些屬性和方法的時候,我們就可以不需要重寫那些已經寫過的方法。

我們也可以對繼承的方法進行覆蓋重寫。具體容後再說

繼承的定義:

就是子類繼承父類的屬性和行為,使得子類物件具有與父類相同的屬性、相同的行為。子類可以直接訪問父類中的非私有的屬性和行為。

繼承的好處:

  1. 提高程式碼的複用性。
  2. 類與類之間產生了關係,是多型的前提。

繼承的格式:

class 父類 {
...
}
class 子類 extends 父類 {
...
}

我們在子類中進行一個變數的定義,如果定義父類中未曾出現的變數,這是可以嗎?

答案是可以的,子類中出現與父類不同的變數,是可以的。

子父類中出現了同名的成員變數時,在子類中需要訪問父類中非私有成員變數時,需要使用super 關鍵字,修飾父類成員變數,類似於之前學過的 this 。

使用格式:

super.父類成員變數名

Fu 類中的成員變數是非私有的,子類中可以直接訪問。若Fu 類中的成員變數私有了,子類是不能直接訪問的。通常編碼時,我們遵循封裝的原則,使用private修飾成員變數,那麼如何訪問父類的私有成員

變數呢?對!可以在父類中提供公共的getXxx方法和setXxx方法。

我們需要進行父類方法的重寫,我們應該如何去操作呢?

如果子類父類中出現重名的成員方法,這時的訪問是一種特殊情況,叫做方法重寫 (Override)。

方法重寫 :子類中出現與父類一模一樣的方法時(返回值型別,方法名和引數列表都相同),會出現覆蓋效果,也稱為重寫或者複寫。宣告不變,重新實現。

建議:在子類重寫的方法體上@override

注:

  1. 子類方法覆蓋父類方法,必須要保證許可權大於等於父類許可權。
  2. 子類方法覆蓋父類方法,返回值型別、函式名和引數列表都要一模一樣。

過載(overroad):可以不同的引數列表

關於構造方法:

  1. 構造方法的名字是與類名一致的。所以子類是無法繼承父類構造方法的。
  2. 構造方法的作用是初始化成員變數的。所以子類的初始化過程中,必須先執行父類的初始化動作。子類的構造方法中預設有一個super() ,表示呼叫父類的構造方法,父類成員變數初始化後,才可以給子類使用(super方法只能出現在構造方法的第一行)

super和this的含義

super :代表父類的儲存空間標識(可以理解為父親的引用)。

this :代表當前物件的引用(誰呼叫就代表誰)。

super和this的用法

  1. 訪問成員
this.成員變數 ‐‐ 本類的
super.成員變數 ‐‐ 父類的
this.成員方法名() ‐‐ 本類的
super.成員方法名() ‐‐ 父類的
  1. 訪問構造方法
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();
}

繼承抽象類的子類必須重寫父類所有的抽象方法。否則,該子類也必須宣告為抽象類。最終,必須有子類實現該父類的抽象方法,否則,從最初的父類到最終的子類都不能建立物件,失去意義。

注意事項:

關於抽象類的使用,以下為語法上要注意的細節,雖然條目較多,但若理解了抽象的本質,無需死記硬背。

  1. 抽象類不能建立物件,如果建立,編譯無法通過而報錯。只能建立其非抽象子類的物件。
  2. 抽象類中,可以有構造方法,是供子類建立物件時,初始化父類成員使用的。
  3. 抽象類中,不一定包含抽象方法,但是有抽象方法的類必定是抽象類。
  4. 抽象類中,不一定包含抽象方法,但是有抽象方法的類必定是抽象類。
  5. 抽象類的子類,必須重寫抽象父類中所有的抽象方法,否則,編譯無法通過而報錯。除非該子類也是抽象類。

關於繼承的小案例,發紅包

這裡給出具體程式碼,加深理解,我就不進行詮釋了

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檔案註釋我就沒有進行一個撰寫了,因為比較的簡單,希望各位同行多多指教!