在第16節繼承中,有父類 Peoplejava
People people=new People(); people.sayHi();
實例化People是沒有意義的,由於「人」是一個抽象的概念。編程
怎麼才能避免父類的實例化呢?使用 abstract
關鍵字修飾類(抽象類)。框架
抽象父類ide
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.javathis
//英國人 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 修飾的類是抽象類,抽象類不能實例化code
被關鍵字 abstract 修飾的方法是抽象方法,抽象方法沒有方法體繼承
抽象方法必須在抽象類裏dns
抽象方法必須在子類中被實現,除非子類是抽象類
抽象方法沒有方法體
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.更容易更換實現
搜索關注公衆號「享智同行」,第一時間獲取技術乾貨