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、抽象类中可以实现接口,并且不实现接口中方法(不重写方法),而接口只能继承接口,不能实现接口 * 注意: * 在实际的项目开发过程中,如果可以使用接口,尽量使用接口,将单继承的父类留在 * 最关键的地方 */