1. 程式人生 > 實用技巧 >java學習-多型、抽象類、介面

java學習-多型、抽象類、介面

一、多型

  1.1多型的概述

  1. 多型是面向物件一大特徵
  2. 多型 : 表示事物的多種形態(事物的多種表現形式)
  3. 多型發生的前提:

    1)需要具有子父類的繼承關係(類與介面實現關係)

    2)子類重寫從父類繼承來的方法

    3)父類的引用指向子類的物件

  舉例 :

  class Person{}

  class Doctor extends Person{}

  class Teacher extends Person{}

  多型表示式:

  Person p; // 父類引用

  new Doctor(); // 子類物件

  new Teacher() ;// 子類物件

  Person p = new Doctor(); // 人類p的表現形式是醫生

  Person p1 = new Teacher(); // 人類p1的表現形式是教師

  以上表達式能體現出人類的多種表現形式,這就是多型的概念

程式碼

public class Person {
    public void eat() {
        System.out.println("人都需要吃飯");
    }
}
public class Doctor extends Person {
    @Override
    public void eat() {
        System.out.println("醫生吃的比較清淡");
    }
}
public
class Teacher extends Person { @Override public void eat() { System.out.println("教師今天想吃涼皮"); } }
public class TestDuoTai {
    public static void main(String[] args) {
        // 多型表示式
        Person p = new Doctor();
        p.eat();// 醫生吃的比較清淡
        
        Person p1 = new Teacher();
        p1.eat();
// 教師今天想吃涼皮 } }

  1.12多型中成員方法的特點

  1. 編譯看左,執行看右

  使用多型表示式呼叫成員方法

    1)編譯看左 : 編譯程式碼時, 如果多型表示式呼叫的這個方法, 在  等號的左邊的型別中不存在(沒定義), 那麼直接報錯,無法編譯通過. 如果等號左邊的型別中存在呼叫的方法,編譯成功

    2)執行看右 : 使用多型的表示式呼叫方法,執行時動態繫結等號右邊的型別中的方法實現, 實際執行的就是等號右邊子類中的重寫方法

程式碼

public class Person {
    public void eat() {
        System.out.println("人都需要吃飯");
    }
}

public class Doctor extends Person {
    @Override
    public void eat() {
        System.out.println("醫生吃的比較清淡");
    }
    
    // 醫生特有的救人功能
    public void savePerson() {
        System.out.println("醫生可以治病救人");
    }
}
public class Teacher extends Person {
    @Override
    public void eat() {
        System.out.println("教師今天想吃涼皮");
    }
    
    // 老師特有功能授課
    public void teach() {
        System.out.println("老師可以授課");
    }
}
public class TestDuoTai {
    public static void main(String[] args) {
        // 多型表示式
        // 1. 編譯看左,執行看右
        Person p = new Doctor();
        // eat方法在等號左邊的型別Person中存在(定義)
        p.eat();//醫生吃的比較清淡
        // savePerson方法在等號左邊的型別Person中不存在,因此報出編譯錯誤
        // p.savePerson(); //The method savePerson() is undefined for the type Person
        
        Person p1 = new Teacher();
        p1.eat();//教師今天想吃涼皮
        // p1.teach();
    }
}

  1.3多型的向上和向下轉型

  1. 多型向上轉型 : 父類的引用指向子類物件(多型表示式)

  Person p = new Doctor();

  向上轉型的實質 : 物件引用p使用範圍縮小, 只能使用子父類中的共有方法

  2.多型向下轉型 :

  目的 : 為了解決多型表示式中,無法使用子類特有方法的侷限性, 想要使用子類中的特有方法功能

  多型向下轉型公式: 將指向子類物件的父類引用, 恢復成子類型別

  舉例 : Doctor d = (Doctor)p;

  向下轉型實質 : 物件引用p使用範圍變大, 可以使用子類中的內容

  1.4多型的好處

  1. 多型好處 : 提高程式碼的擴充套件性
  2. 方法的引數列表上 : 定義一個方法功能, 形式引數可以是父類資料型別, 在方法中可以使用父類引數中的任意功能; 當呼叫這個方法時, 實際引數可以是當前父類型別物件本身,也可以是這個父類的任意一個子類型別物件
  3. 一個型別不一定非通過new物件才能建立, 很多情況下, 方法功能返回值型別就是引用資料型別, 需要一個對應的引用型別接方法返回值, 若這個引用的具體型別不清楚,可以直接使用一個父類型別作為這個方法的返回值型別承接

需求 : 現有一農場,需要設計出一個方法, 功能是提供不同的動物型別,能輸出每一種動物需要投喂的食物, 請根據多型設計出這個方法功能

舉例 : 給該方法傳遞貓型別資料 : 提示, 餵魚 ; 給該方法傳遞狗型別資料 : 提示 , 吃骨頭; 給該方法傳遞羊型別資料 : 提示 , 喂草 .... 每一種動物都能得到對應的餵食結果

程式碼

public class Animal {
     // 將所有動物都需要餵食功能 : eat
     public void eat() {
         System.out.println("所有動物都需要餵食");
     }
}

public class Cat extends Animal {
         @Override
         public void eat() {
             System.out.println("貓餵魚");
         }
}
public class Dog extends Animal {
     @Override
     public void eat() {
         System.out.println("狗喂骨頭");
     }
}
public class Farmer {
     // 方法功能 : 將每一種動物餵食結果顯示出來
     public void wei(Animal a) {// Animal a = new Sheep();
         a.eat();
     }
     
     public void useI(int i) {// int i = 10;
         System.out.println(i);
     }
}

二、抽象類

  2.1抽象方法和抽象類

  1. 抽象 : 表示無法使用語言進行描述, 無法實現的, 虛無縹緲,沒有具體存在

  將事物的共性向上抽取,抽取到父類中, 但是當共性抽取到一定程度時, 父類中不知道如何實現共性內容才能讓每一個子類都滿足實際需求, 於是父類中將共性方法只做方法的宣告,而沒有方法的實現,這樣的方法稱為抽象方法

  2.抽象方法的定義:

    需要使用關鍵字 : abstract

    修飾符 abstract 返回值型別 方法名(引數列表);

  3.抽象類的定義:

    修飾符 abstract class 類名{

  // 抽象方法只能存在於抽象類中

    }

  4.抽象方法存在是為了為子類限定一些需要實現的規則

程式碼

public abstract class Animal {

    // 抽象方法
    // The abstract method eat in type Animal can only be defined by an abstract class
    // 抽象方法只能定義在抽象類中
    public abstract void eat();
}

2.2抽象的特點

  1. 抽象類和抽象方法都需要使用 abstract 抽象關鍵字

  public abstract class Animal{

public abstract void eat();

    }

  2.抽象類和抽象方法之間的關係:

    1)抽象方法必須定義在抽象類中

    2)抽象類中可以沒有抽象方法

  3.抽象類的例項化(例項化 : new物件)

    1)抽象類不能例項化物件(不能new物件)

  因為抽象類中可以含有抽象方法, 而抽象方法因為沒有方法體,不能執行的,因此抽象類不能new物件

    2)抽象類等著當父類,等著被子類繼承, 需要一個子類繼承這個抽象類, 讓子類將抽象父類中的所有抽象方法全部重寫, 通過建立子類物件,實現方法的呼叫

  4.抽象類的子類前途:

    1)子類將抽象父類中的所有抽象方法全部重寫, 子類可以正常建立物件使用

    2)子類沒有將抽象父類中的所有抽象方法全部重寫, 子類仍然還是一個抽象類

  2.3抽象類中的成員

    抽象類中的成員 : 先把抽象類當做一個普通類, 在此基礎上可以定義抽象方法

  1.可以定義成員變數

  2.可以定義構造方法

  一個型別是否可以定義構造方法,與這個型別能否建立物件無關, 與型別中是否能定義成員變數有關. 只要一個型別中可以定義成員變數,那麼這個型別就可以定義構造方法

  3.可以定義非抽象方法

  為了給子類直接繼承使用

  4.可以定義抽象方法

  為了給子類限定需要實現的規則

抽象的練習 :

  每個員工Employee都具有屬性(姓名,工號,工資),行為 : 工作

程式設計師類: 屬性(姓名,工號,工資,獎金), 行為 : 工作(軟體開發)

  測試工程師類 : 屬性(姓名,工號,工資), 行為 : 工作(軟體測試)

  專案經理類 : 屬性(姓名,工號,工資,獎金),行為 : 工作(控制工作進度)

請設計出合適的類關係,並測試
程式碼

public abstract class Employee {
    // 姓名,工號,工資
    private String name;
    String id;
    double salary;
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    public abstract void work();
}
public class Employee_程式開發 extends Employee{    
    private double jiangjin;    

    public Employee_程式開發(String name , String id, double salary, double jiangjin) {
        super();
        this.jiangjin = jiangjin;
        this.id = id;
        setName(name);
        this.salary = salary;
    }
    
    public Employee_程式開發() {
        super();
    }

    public double getJiangjin() {
        return jiangjin;
    }

    public void setJiangjin(double jiangjin) {
        this.jiangjin = jiangjin;
    }

    @Override
    public void work() {
    System.out.println(getName() +"---"+ id +"---"+ salary + "---"+jiangjin+"程式設計師做開發");
    }

}
public class Employee_測試工程師 extends Employee{

    @Override
    public void work() {
        System.out.println("測試工作");
    }
}
public class TestEmployee {

    public static void main(String[] args) {
        Employee_程式開發 e1 = new Employee_程式開發("小張","007",15678.99,3200);
        e1.work();    
        Employee_測試工程師 e2 = new Employee_測試工程師();
        e2.work();
    }
}

三、介面

  3.1介面的概述

  1. 介面 : 一系列規則的集合, 介面中都是抽象方法
  2. 介面好處:

因為介面中全部都是抽象方法, 抽象方法只方法的宣告, 方法功能的宣告和方法的實現分離, 讓型別與型別之間的耦合度(關聯度)降低

  3.2介面的定義

  1. 介面的定義 :

  使用關鍵字 interface : 用於定義出介面型別

  修飾符 interface 介面名{

// 抽象方法(隨著JDK版本的推進, 介面中不僅僅只有抽象方法,目前學習中,以抽象方法為學習重點,JDK8新特性,講解介面中的其他方法定義)

}

程式碼

public interface MyInter {
    // 定義抽象方法
    public abstract void fun();
    
    public abstract boolean equalDouble(double d, double d1);
}

  3.3介面的特點

  1. 介面中的方法都是抽象方法
  2. 介面不能例項化物件(不能new物件)

介面需要一個實現類, 將介面中的所有抽象方法重寫,通過建立實現類物件,呼叫重寫方法

  3.類與介面之間的關係:實現關係 implements (與類和類之間的繼承extends關係非常相似)

舉例 : interface MyInter{}

class MyInterImpl implements MyInter{

// 將介面中的抽象方法全部重寫;

}

  4.介面實現類的前途:

    1)如果實現類將介面中的所有抽象方法全部重寫,那麼這個實現類可以正常使用

    2)如果實現類沒有將介面中的所有抽象方法全部重寫, 那麼這個實現類是抽象類, 抽象類不能例項化物件

  3.4介面中的成員

  1. 成員常量 : 介面中的所有成員變數都是常量, 因為介面中的成員變數有預設修飾, public static final, 寫出修飾或者不寫,以及寫出修飾符的一部分, 預設修飾不變
  2. 介面中無法定義構造方法: 因為介面中沒有成員變數
  3. 抽象方法 : 有預設修飾符, public abstract