9.5 概述
抽象方法中所有的方法都是抽象的。这时,可以把抽象类用另一种形式来表示——接口。
初期可以理解为接口是特殊的抽象类。
abstract class AbsDemo{
abstract void show1();
abstract void show2();
}
定义接口:
interface Inter{
public static final int NUM = 4;
public abstract void show1();
public abstract void show2();
}
接口中的成员和class定义不同之处:
接口中常见的成员有两种:全局变量和抽象方法。而且都有固定的修饰符。
共性:成员都是public修饰的。
9.6 特点
- 接口不可以实例化。
- 需要覆盖了接口中的所有的抽象方法的子类。才可以实例化。否则,该子类还是一个抽象类。
- 接口是用来实现的。类与接口的关系的实现关系(implements)
interface Inter{
public static final int NUM = 4;
public abstract void show1();
public abstract void show2();
}
class Demo implements Inter{ //实现接口
public void show1(){}
public void show2(){}
}
9.7 多实现
多继承,好处:可以让子类具备更多的功能,弊端:调用的不确定性。Java中不直接支持多继承,而是对该机制进行改良。通过接口来解决问题。
接口的好处或者解决了什么问题呢?
通过接口来解决问题,将多继承转换成了多实现。
interface InterA{
void show1();
}
interface InterB{
void show2();
}
class SubInter implements InterA,InterB{ // 实现两个接口
public void show1(){
System.out.println("show1");
}
public void show2(){
System.out.println("show2");
}
}
多实现可以避免调用的不确定性,例如InterA和InterB都有show()方法,但是它们的show方法都没有方法体,所以子类对象调用show方法,就是子类中实现了的show方法,不会调用两个接口中show方法。
interface InterA{
void show();
}
interface InterB{
void show();
}
class SubInter implements InterA,InterB{
public void show(){
System.out.println("show");
}
}
9.8 避免了单继承的局限性
一个类继承一个类的同时,还可以实现多个接口,避免了单继承的局限性。
继承是为了获取体系的基本功能,想要扩展功能可以通过实现接口来完成。
class Fu{
void show(){
System.out.println("fu show");
}
}
interface Inter0{
void show1();
}
class Zi extends Fu implements Inter0{
public void method(){
System.out.println("zi method");
}
public void show1(){
System.out.println("zi show1");
}
}
class Test{
public static void main(String[] args){
Zi z = new Zi();
z.show();
z.method();
z.show1();
}
}
9.9 接口多继承&没有抽象方法的抽象类
类与类之间:继承关系(is-a)
类与接口:实现关系(like-a)
接口和接口的关系?继承关系,还可以多继承
interface InterA{
void show1();
}
interface InterB{
void show2();
}
interface InterC extends InterA,InterB{
void show3();
}
class SubInter implements InterC{
public void show1(){
System.out.println("show1");
}
public void show2(){
System.out.println("show2");
}
public void show3(){
System.out.println("show3");
}
}
问题
只需要部分功能,但是为了实例化,必须要全部覆盖,代码复用性很差。
interface Inter_{
void show1();
void show2();
void show3();
}
class DemoA implements Inter_{
public void show1(){
System.out.println("show1");
}
public void show2(){}
public void show3(){}
}
class DemoB implements Inter_{
public void show1(){ }
public void show2(){
System.out.println("show2");
}
public void show3(){}
}
解决方法
为了方便创建Inter_接口的子类对象,可以用一个类先把接口中的所有方法都空实现,该类创建对象没有意义,所以可以将该类抽象。注意这里不能将该类的构造函数私有化,因为构造函数私有化后,不能有子类。
所以想让一个类不能创建对象,并且可以有子类的,就可以让该类抽象。
interface Inter_{
void show1();
void show2();
void show3();
}
//没有抽象方法的抽象类,方便创建接口的对象
abstract class Demos implements Inter_{
public void show1(){} //空实现
public void show2(){}
public void show3(){}
}
class DemoA extends Demos{
public void show1(){
System.out.println("show1");
}
}
class DemoB extends Demos{
public void show2(){
System.out.println("show2");
}
}
9.10 接口的思想
笔记本电脑的USB接口:
- 接口的出现拓展了功能
- 接口其实就是暴露出来的规则
- 接口的出现降低了耦合性。解耦。
class Mouse{
}
interface USB{
}
class NewMouse extends Mouse implements USB{ //拓展了USB功能
}
接口的出现,一方在使用接口,一方在实现接口。
9.11 抽象类和接口的区别
例子:
描述犬,里面有吃,叫,都是抽象的。具体由子类来完成。
问题:定义成抽象;类还是定义成接口??
abstract class 犬{
abstract void 吃();
abstract void 叫();
}
interface 犬{
abstract void 吃();
abstract void 叫();
}
//添加一个功能。缉毒。单独描述一个缉毒功能犬。
class 缉毒犬 extends 犬{
void 吃(){}
void 叫(){}
void 缉毒(){}
}
class 缉毒犬 implements 犬{
public void 吃(){} //必须是public
public void 叫(){}
void 缉毒(){}
}
缉毒犬是犬中得一种,is a的关系。
犬用于描述所有功能犬的基本功能,用class定义,父类。
所以犬不适合定义成接口。
class 缉毒猪{
void 缉毒(){}
}
具备缉毒功能的有很多,缉毒功能需要抽取。抽取到类中,还是抽取到接口中??
都试一下:
先定义成类。
abstract class 缉毒{
abstract void 缉毒();
}
不行,缉毒犬继承犬类,就不能继承其他类,因为类不能多继承。
定义成接口试试。
abstract class 犬{
abstract void 吃();
abstract void 叫();
}
interface 缉毒{
abstract void 缉毒();
}
class 缉毒犬 extends 犬 implements 缉毒{
void 吃(){}
void 叫(){}
public void 缉毒(){}
}
这是可以的。
抽象类和接口的区别:
- 类用于描述事物的基本功能。
接口用于定于事物的额外功能。 - 类与类之间的继承关系:is a
类与接口是实现关系:like a - 抽象类中可以定义抽象和非抽象的方法,子类可以直接使用,或者覆盖使用。
接口中定义都是抽象方法,必须实现才能用 - 抽象类里面有构造函数
接口里面没有构造函数