12-接口
一、接口
▪ 我们前面用继承关系,描述了动物、哺乳动物、爬行动物的各种
关系。
▪ 现在我们要描述:
– 飞机 导弹 子弹 篮球 石头的关系?
他们之间有继承关系吗?没有
他们的共同特征都有飞的方式
这个飞的方式我们就可以用接口来定义。
▪如何定义接口?
–格式:
▪[访问修饰符] interface 接口名 [extends 父接口1,父接口2…] {
–常量定义 //总是public static final
–方法定义 //总是:public abstract
▪}
▪如何实现接口
–子类通过implements来实现接口中的规范
–接口丌能创建实例,但是可用于声明引用变量类型。
–一个类实现了接口,必须实现接口中所有的方法,并且这些方法只能是public的。
–Java的类只支持单继承,接口支持多继承
例子:
▪ 要求实现防盗门的功能
门有“开”和“关”的功能,锁有“上锁”和“开锁”的功能
将门和锁分别定义为抽象类
/* 防盗门是一个门, 防盗门上也具有一个锁, 因此将门和锁定义为抽象类, 防盗门相当于具体的子类实现 */
public abstract class Door { // 打开门 public abstract void openDoor(); // 关闭门 public abstract void closeDoor(); }
public abstract class Lock { public abstract void openLock(); public abstract void closeLock(); }
子类实现的时候因为java不允许多继承, 因此java中有另一种方式interface
防盗门可以继承门的同时又继承锁吗?
如何解决这个问题呢?
将门定义为抽象类,锁定义为接口
防盗门继承门,实现锁的接口
Lock.java
public interface Lock { public final int a = 200; void openLock(); void closeLock(); }
public class LockDoor extends Door implements Lock{ @Override public void openDoor() { System.out.println("开门"); } @Override public void closeDoor() { System.out.println("关门"); } @Override public void openLock() { System.out.println("开锁"); } @Override public void closeLock() { System.out.println("关锁"); } }
public class TestLockDoor { public static void main(String[] args) { LockDoor lockDoor = new LockDoor(); // Lock lock = new Lock(); lockDoor.openDoor(); lockDoor.openLock(); lockDoor.closeDoor(); lockDoor.closeLock(); } }
打印结果:
/* 开门 开锁 关门 关锁 Process finished with exit code 0 */
/* * java中的继承关系是单继承,如果拥有多个父类的时候,可以考虑使用接口进行实现 * java中的接口具备广泛的使用: * 用法: * 使用interface来修饰 * 接口中可以包含多个方法,且方法跟抽象类中的抽象方法一致,可以不写实现,子类在实现的时候必须要实现代码逻辑 * 子类实现接口使用implements关键字 * 特征: * 1、接口中的所有方法都是抽象方法,不能包含方法的实现 * 2、接口中的所有方法的访问修饰权限都是public,不写并不是默认访问权限,而是public * 3、接口不能被实例化 * 4、接口的子类必须要实现接口中的所有方法,跟抽象类有所不同,抽象类中的抽象方法必须要被子类实现 * 5、子类可以拥有实现多个接口 * 6、接口中的变量都是静态常量,如果变量没有使用static关键字修饰,它也表示静态常量,不用final关键字修饰,也是常量 * 7、接口中的方法和常量无论是否添加public修饰,默认的权限有且仅有一个,就是public * * 接口的使用: * 1、接口代表一种能力,接口中可以定义N多个方法,子类在进行实现的时候,必须要实现这些方法 * 将这些方法进行实现,就意味着具备了方法的能力 * 关心实现类有何能力,而不关心实现细节 * * */
验证"特征 第6点"
public class TestLockDoor { public static void main(String[] args) { LockDoor lockDoor = new LockDoor(); // Lock lock = new Lock(); lockDoor.openDoor(); lockDoor.openLock(); lockDoor.closeDoor(); lockDoor.closeLock(); lockDoor.photo(); System.out.println(LockDoor.a); LockDoor.a = 300; } }
报错:
java: 无法为最终变量a分配值
防盗门是一个门 is a 的关系
防盗门有一个锁 has a 的关系
-上锁
-开锁
Door现在是一个抽象类, 其实改成接口也是可以运行的, 什么时候用抽象类什么时候用接口呢?
例子:
▪ 扩展防盗门门铃功能,主要是实现拍照存档
public interface DoorBell { void photo(); }
public class LockDoor extends Door implements Lock,DoorBell { @Override public void openDoor() { System.out.println("开门"); } @Override public void closeDoor() { System.out.println("关门"); } @Override public void openLock() { System.out.println("开锁"); } @Override public void closeLock() { System.out.println("关锁"); } @Override public void photo() { System.out.println("拍照存档"); } }
public class TestLockDoor { public static void main(String[] args) { LockDoor lockDoor = new LockDoor(); // Lock lock = new Lock(); lockDoor.openDoor(); lockDoor.openLock(); lockDoor.closeDoor(); lockDoor.closeLock(); lockDoor.photo(); System.out.println(LockDoor.a); // LockDoor.a = 300; } }
1、接口是一种能力
例子:
▪ 用程序描述USB接口
当实现了这个接口,就意味着具备某种能力。接口表示一种能力
对应接口的使用1
public interface Usb { // 信息传输 public void dataTransfer(); public void play(); }
public class Mouse implements Usb{ @Override public void dataTransfer() { System.out.println("鼠标来点击屏幕"); } @Override public void play() { System.out.println("鼠标在自己玩"); } }
public class UPan implements Usb { @Override public void dataTransfer() { System.out.println("upan可以传输数据"); } @Override public void play() { } }
public class Test { public static void main(String[] args) { Mouse mouse = new Mouse(); mouse.dataTransfer(); UPan up = new UPan(); up.dataTransfer(); } }
运行结果为:
/* 鼠标来点击屏幕 upan可以传输数据 Process finished with exit code 0 */
此时有一个无论什么比如AAA, 也实现了接口
public class AAA implements Usb { @Override public void dataTransfer() { System.out.println("AAA 进行数据传输"); } @Override public void play() { } }
将这些方法进行实现,就意味着具备 了方法的能力
例子
-使用接口实现手机功能
▪ 需求说明:
– 原始的手机,可以发短信,通电话。随着发展,手机增加了功能:音频、视
频播放、拍照、上网。
2、接口是一种约定
▪ 生活中,我们使用的两相电源揑座,规定了:
– 两个接头间的额定电压
– 两个接头间的距离
– 接头的形状
▪ 接口是一种约定
体现在接口名称和注释上
有些接口只有名称
方法的实现方式要通过注释来约定
3、面向接口编程
程序设计时面向接口的约定而不考虑具体实现
3.1、练习1
/* ▪ 开发打印机 – 墨盒:彩色、黑白 – 纸张类型:A4、B5 – 墨盒和纸张都丌是打印机厂商提供的 – 打印机厂商要兼容市场上的墨盒、纸张 */
public interface InkBox { /* * 墨盒 * */ // 黑白 public void getWriteAndBlock(); // 彩色 public void getColor(); }
public interface Paper { /* * 纸张 * */ public void getA4(); public void getB5(); }
public class CopyMechine implements InkBox,Paper { @Override public void getWriteAndBlock() { System.out.println("使用黑白墨盒打印"); } @Override public void getColor() { System.out.println("使用彩色墨盒打印"); } @Override public void getA4() { System.out.println("使用A4纸打印"); } @Override public void getB5() { System.out.println("使用B5纸打印"); } public static void main(String[] args) { CopyMechine copyMechine = new CopyMechine(); copyMechine.getWriteAndBlock(); copyMechine.getA4(); } }
3.2、练习2
/* ▪ 训练要点: – 接口的基础知识 – 理解接口表示一种约定 ▪ 需求说明: – 采用面向接口编程思想组装一台计算机。 – 计算机的主要组成部分有: ▪ CPU ▪ 硬盘 ▪ 内存 */
思路:
/* ▪ 实现思路: – 定义CPU的接口CPU,返回CPU品牌和主频 – 定义内存的接口EMS,返回容量。 – 定义硬盘的接口HardDisk,返回容量。 – 编写各组件厂商分别实现CPU、EMS、和HardDisk接口编写计 算机类,组装计算机并显示相关信息 – 编写测试类运行 */
定义接口
public interface CPU { public static final String str = "hehe"; // 品牌 public String getBrand(); // 主频 public String getHZ(); }
public interface Memory { // 容量 public String getCapacity(); }
public interface HardDisk { // 容量 public String getVolumn(); }
具体子类实现
CPU
intel的cpu
public class InterCpu implements CPU { @Override public String getBrand() { return "inter"; } @Override public String getHZ() { return "2000"; } }
Amd的cpu
public class AmdCpu implements CPU { @Override public String getBrand() { return "amd"; } @Override public String getHZ() { return "1000"; } }
硬盘
三星
public class SXHardDisk implements HardDisk{ @Override public String getVolumn() { return "三星"; } }
金士顿
public class JSDHardDisk implements HardDisk { @Override public String getVolumn() { return "金士顿"; } }
内存一样
computer实现接口
public class Computer implements CPU,HardDisk{ public void show(CPU cpu,HardDisk hardDisk){ System.out.println("计算机的组成如下:"); System.out.println("cpu:"+cpu.getBrand()+" ,主频是:"+cpu.getHZ()); System.out.println("硬盘容量是:"+hardDisk.getVolumn()); } @Override public String getBrand() { return null; } @Override public String getHZ() { return null; } @Override public String getVolumn() { return null; } }
测试类
public class Test { public static void main(String[] args) { Computer computer = new Computer(); CPU cpu = new InterCpu(); HardDisk hardDisk = new JSDHardDisk(); computer.show(cpu,hardDisk); } }
打印结果为:
/* 计算机的组成如下: cpu:inter ,主频是:2000 硬盘容量是:金士顿 Process finished with exit code 0 */
▪ 阅读代码,找出错误
不能有构造方法
不能对方法进行实现
修饰符不能是private
▪ 为什么需要接口?接口和抽象类的区别?
– 接口就是比“抽象类”还“抽象”的“抽象类”,
/* 抽象类也好、接口也好、类也好,我们定义的时候都是由具象到抽象的过程, 在识别过程中, 抽象类里面定义的方法是不需要写方法实现的, 在抽象方法里可以写也可不写,普通方法必须要写方法实现, 在接口中,不论怎么定义,方法默认都是抽象方法,就不能包含实现 */
可以更加规范的对子类迚行约束。
全面地专业地实现了:规范和具体实现的分离。
– 接口就是规范,定义的是一组规则,体现了现实世界中“如果你是…则必须
能…”的思想。如果你是天使,则必须能飞。如果你是汽车,则必须能跑。如果你好人,则必须干掉坏
人;如果你是坏人,则必须欺负好人。
– 接口的本质是契约,就像我们人间的法律一样。制定好后大家都遵守。
– 项目的具体需求是多变的,我们必须以不变应万变才能从容开发,此处的
“不变”就是“规范”。因此,我们开发项目往往都是面向接口编程!
▪ 接口相关规则
– 接口中所有方法都是抽象的。
– 卲使没有显式的将接口中的成员用public标示,也是public访问类型的
– 接口中变量默认用 public static final标示,所以接口中定义的变量就是全
局静态常量。
public interface A { public void show(); }
public interface B extends A{ }
– 可以定义一个新接口,用extends去继承一个已有的接口,如果是 B implements A 会报错 No implements clause allowed for interface
– 可以定义一个类,用implements去实现一个接口中所有方法。
之前的都是这样的
– 可以定义一个抽象类,用implements去实现一个接口中部分方法
public abstract class C implements A{ // @Override // public void show(){ // System.out.println("show"); // } }
不重写show方法也没问题, 因为是一个抽象类,可以有实现也可以不实现, 看具体情况
/* ▪ C++支持多重继承,Java支持单重继承 ▪ C++多重继承的危险性在于一个类可能继承了同一个方法的丌同实 现,会导致系统崩溃。 ▪ Java中,一个类只能继承一个类,但同时可以实现多个接口,既可 以实现多重继承的效果和功能,也避免的多重继承的危险性。 ▪ class Student extents Person implements Runner,Flyer ▪ {…} ▪ 注意:extends 必须位于implements乊前 */
二、什么时候用接口, 什么时候用抽象类?
/* 抽象类和接口的区别: * 1、抽象类中的方法可以有抽象方法,也可以有普通方法,但是接口中只能包含抽象方法 * 2、抽象类需要使用abstract关键字来修饰,而接口使用interface关键字来修饰 * 3、子类使用extends关键字来继承抽象类,使用implements来实现接口 * 4、子类继承抽象类的时候必须要实现所有的抽象方法,普通方法可以不重写,而接口中的所有方法必须实现 * 5、抽象类中可以定义成员变量,而接口中只能定义静态常量 * 6、抽象类在子类实现的时候是单继承,而接口时多继承 * 7、抽象类和接口都不能实例化,但是抽象类中可以有构造方法,而接口中不能有构造方法 * 8、抽象类中可以实现接口,并且不实现接口中方法(不重写方法),而接口只能继承接口,不能实现接口 * 注意: * 在实际的项目开发过程中,如果可以使用接口,尽量使用接口,将单继承的父类留在 * 最关键的地方 */