1. 程式人生 > >Java入門系列-18-抽象類和介面

Java入門系列-18-抽象類和介面

抽象類

在第16節繼承中,有父類 People

People people=new People();
people.sayHi();

例項化People是沒有意義的,因為“人”是一個抽象的概念。

怎麼才能避免父類的例項化呢?使用 abstract 關鍵字修飾類(抽象類)。

抽象父類

public abstract class People {
    private String name;
    
    public People(String name) {
        super();
        this.name = name;
    }

    //人類共有方法 哭
    public void cry() {
        System.out.println("嗚嗚");
    }
    //抽象方法 不做具體實現
    public abstract void sayHi();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

子類:Chinese.java

//中國人
public class Chinese extends People{

    public Chinese(String name) {
        super(name);
    }

    //必須實現
    @Override
    public void sayHi() {
        System.out.println(this.getName()+":你好!");
    }
}

子類:Britisher.java

//英國人
public class Britisher extends People{

    public Britisher(String name) {
        super(name);
    }

    @Override
    public void sayHi() {
        System.out.println(this.getName()+":Hello!");
    }
}

測試類

public class TestPeople {

    public static void main(String[] args) {
        //People people=new People("張三");//去掉註釋試試
        People chinese=new Chinese("張三");
        chinese.sayHi();
        People britisher=new Britisher("John");
        britisher.sayHi();
    }
}

被關鍵字 abstract 修飾的類是抽象類,抽象類不能例項化

被關鍵字 abstract 修飾的方法是抽象方法,抽象方法沒有方法體

抽象方法必須在抽象類裡

抽象方法必須在子類中被實現,除非子類是抽象類

抽象方法沒有方法體 public abstract void sayHi();

注意:被 abstract 修飾後不能使用 final 修飾!

介面

如何實現防盜門這個類?門有“開”和“關”的功能,鎖有“上鎖”和“開鎖”的功能,將門和鎖分別定義為抽象類。但是防盜門可以繼承門的同時又繼承鎖嗎?不能,防盜門不是鎖,不符合 is a 的關係而且Java只支援單繼承。

介面的語法

public interface MyInterface {
    public abstract void foo();
}

介面可以認為是純粹的抽象類

介面中的方法都是抽象方法 (public abstract)

介面不可以被例項化

實現類必須實現介面中的所有方法

介面中的變數都是靜態常量

介面之間可以互相繼承(extedns),類只能實現介面(implements)

一個類可以繼承一個父類,實現多個介面

演示介面的繼承及實現介面

父介面:A.java

public interface A {
    void methodA();
}

子介面:B.java

public interface B extends A{
    void methodB();
}

介面的實現類:C.java

public class C implements B{

    @Override
    public void methodA() {
    }

    @Override
    public void methodB() {
    }
}

介面表示能力

面向介面程式設計時,關心實現類有何能力,而不關心實現細節。面向介面的約定而不考慮介面的具體實現。

在鳥類中,白鷺可以飛,鴕鳥不能飛,所以在這裡飛是一種能力,下面看一下程式碼的設計。

飛行介面:Fly.java

//表示飛行能力
public interface Fly {
    /**
     * 飛行
     */
    public abstract void fly();
}

游泳介面:Swim.java

//表示游泳能力
public interface Swim {
    public abstract void swim();
}

鳥類:Bird.java

//抽象鳥類 重用程式碼
public abstract class Bird {
    /**
     * 下蛋
     */
    public void layEggs() {
        System.out.println("產出一枚蛋");
    }
}

白鷺類:Egret.java

//白鷺類
public class Egret extends Bird implements Fly,Swim{

    @Override
    public void fly() {
        System.out.println("使勁煽動翅膀後起飛");
    }

    @Override
    public void swim() {
        System.out.println("漂在了水面上,輕鬆的游來游去");
    }
}

鴕鳥類:Ostrich.java

//鴕鳥類
public class Ostrich extends Bird implements Swim{

    @Override
    public void swim() {
        System.out.println("漂在了水面了,開始遊動");
    }
}

測試類

public class TestBird {
    public static void main(String[] args) {
        Egret egret=new Egret();
        egret.swim();
        egret.fly();
        Ostrich ostrich=new Ostrich();
        ostrich.swim();
    }
}

介面表示約定

在生活中,我們使用的插座,規定了兩個接頭剪得額定電壓、兩個接頭間的距離、接頭的形狀。

在程式碼中約定體現在介面名稱和註釋上

下面使用面向介面程式設計實現一臺計算機的組裝,計算機的組成部分有:CPU、硬碟、記憶體。

先建立 CPU、硬碟、記憶體介面

package computer;

/**
 * CPU 介面
 * @author Jack
 *
 */
public interface CPU {
    /**
     * 獲取CPU品牌
     * @return
     */
    String getBrand();
    
    /**
     * 獲取CPU主頻
     * @return
     */
    Float getFrequency();
}
package computer;

/**
 * 硬碟介面
 * @author Jack
 *
 */
public interface HardDisk {
    
    /**
     * 獲取硬碟容量
     * @return
     */
    int getCapacity();
}
package computer;

/**
 * 記憶體介面
 * @author Jack
 *
 */
public interface EMS {
    /**
     * 獲取記憶體容量
     * @return
     */
    int getSize();
}

將介面設計到計算機類中

package computer;
/**
 * 計算機類
 * @author Jack
 *
 */
public class Computer {
    private CPU cpu;//cpu介面
    private HardDisk hardDisk;//硬碟介面
    private EMS ems;//記憶體介面

    public Computer() {
    }

    public Computer(CPU cpu, HardDisk hardDisk, EMS ems) {
        super();
        this.cpu = cpu;
        this.hardDisk = hardDisk;
        this.ems = ems;
    }

    public CPU getCpu() {
        return cpu;
    }

    public void setCpu(CPU cpu) {
        this.cpu = cpu;
    }

    public HardDisk getHardDisk() {
        return hardDisk;
    }

    public void setHardDisk(HardDisk hardDisk) {
        this.hardDisk = hardDisk;
    }

    public EMS getEms() {
        return ems;
    }

    public void setEms(EMS ems) {
        this.ems = ems;
    }
}

建立 CPU、硬碟、記憶體介面的實現

package computer.impl;

import computer.CPU;

/**
 * 英特爾 CPU
 * @author Jack
 *
 */
public class IntelCPU implements CPU{

    @Override
    public String getBrand() {
        return "英特爾";
    }

    @Override
    public Float getFrequency() {
        return 2.3f;
    }
}
package computer.impl;

import computer.HardDisk;

/**
 * 閃迪硬碟
 * @author Jack
 *
 */
public class SanDisk implements HardDisk{

    @Override
    public int getCapacity() {
        return 3000;
    }
}
package computer.impl;

import computer.EMS;

/**
 * 金士頓 記憶體
 * @author Jack
 *
 */
public class JSDEMS implements EMS{

    @Override
    public int getSize() {
        return 4;
    }
}

完成計算機及元件的組裝進行測試

package computer;

import computer.impl.IntelCPU;
import computer.impl.JSDEMS;
import computer.impl.SanDisk;

public class TestComputer {
    public static void main(String[] args) {
        CPU cpu=new IntelCPU();//建立CPU
        HardDisk sanDisk=new SanDisk();//建立硬碟
        EMS jsdEMS=new JSDEMS();//建立記憶體
        Computer computer=new Computer(cpu,sanDisk,jsdEMS);
        System.out.println("CPU型號:"+computer.getCpu().getBrand());
        System.out.println("硬碟容量:"+computer.getHardDisk().getCapacity()+" GB");
        System.out.println("記憶體容量:"+computer.getEms().getSize()+" GB");
    }
}

介面總結

介面有比抽象類更好的特性: 1.可以被多繼承 2.設計和實現完全分離 3.更自然的使用多型 4.更容易搭建程式框架 5.更容易更換實現

搜尋關注公眾號「享智同行」,第一時間獲取技術乾貨