接口 与 抽象Interface and Abstract
变量类型 与 权限
通过变量类型访问对象方法

Person 访问 Person
通过同类型对象变量访问
1 2 3 Person person = new Person();person.eat();person.work();

Animal 访问 Person
通过父类型对象变量访问
1 2 3!Animal animal = new Person();animal.eat();animal.work();

项目进度推进
attack 方法消除
功能期待
有 attck 就调用 没有 attack 就不调用
一个新的变量类型,仅有 attack 方法,不多不少
接口 x 向上转换
案例

定义接口
什么是 接口
一个变量类型,用于通过它访问对象
在这个类型里所声明的方法,将来就可以访问
方法声明

1 2 3 public interface Calculator { void calculate();}
接口内的方法 默认 public
接口内只能有方法声明
必须 public 所以不需要写 public
接口内的方法不能写实现
仅仅声明, 所以不能写方法实现
接口不可以被 new
接口仅用于对访问进行控制,并不是对象,所以不能被 new
接口不可以属性声明
接口用于描述一套调用的方法,类似方法组
所以不能声明属性
之后会学习到,可以在接口内声明静态属性
类与接口对接
实现声明

1 public class 类名 implements 接口名public class Person implements Calculator
名词
类 实现 接口
接口 / 实现类
效果
声明 implements 接口后,就可以使用 接口作为变量类型,访问对象

1 2 Calculator c = new Person();c.calculate();
类实现接口方法
声明 implements 接口后,这个类必须确保有覆盖这个方法,
也就是对方法进行实现
向上转换
只能调用接口里声明的方法
向上转换、减少保障、降低权限、更多可能
接口 x 调用保障
调用保障分析
接口如何做到可以安全的调用到对应的代码?
对象必须声明实现接口
声明实现接口的类,必须实现接口里所有的方法
接口 x 多态Interface x Polymorphism
多态现象

对同样的对象变量类型 调用 同样的方法
却执行了不一样的代码
多态思维

类型不确定性
调用方
不能确定 到底调的是具体哪个类
也不需要 知道是哪个类
效果不确定性
调用方
不能确定 到底调的是具体哪个方法
也不需要 知道是哪个方法
接口 x 类型转换
instanceof 实质
1 2 3 if (person instanceof Calculator){ ...}
instanceof 用来探测 某个对象所属的类 是否能通过某个访问权限访问
也就是 用来探测 该对象变量是否能够转型为 探测的类型
通过的类型
自己
所有父类
继承链上所有声明实现的接口
接口强制类型转换
1 2 3 Animal animal = new Person();Calculator calculator = (Calculator)animal;calculator.calculate()
编译时写强制类型转换即可通过检查。
运行时会确认 所属对象是否能够提供接口。如果不能,会报错。
类型检测 x 类型转换
先检测 是否 安全
再转型 恢复权限
1 2 3 4 if (obj instanceof Inter) { Inter inter = (Inter)obj; inter.callFunctionViaInterface();}
项目进度跟进
简化 attack 代码
接口语法补充
实现多个接口
一个类可以声明实现多个接口
1 public class Person implements Calculator, Thinking
接口的方法可以重叠,没事。
类需要实现接口里所有的方法
扩展接口
一个接口可以扩展多个接口
1 2 3 4 public interface IA { void f0(); void f1();}
1 2 3 4 public interface IB { void f0(); void f2();}
1 2 3 public interface IC extends IA, IB { void f3();}
继承 和 接口 的对比
语法
extends / class
implements / interface
效果
继承后, 可以使用父类作为访问切面
继承同时, 还能代码重用
接口只用于定义一套新的访问权限
意图
继承主要用于子类扩展功能, 父类分享共性
接口主要用于定义新的访问切面
声明
继承父类, 父类可以有属性 和方法实现
实现接口, 接口只能有方法声明
方法覆盖
继承父类后, 可以选择覆盖父类方法 或者不覆盖
实现接口后, 必须确保实现接口内的方法
数量
一个类只能继承一个类, 多继承会带来调用问题
一个类可以实现多个接口
意义
继承的关系是 是
接口的关系是 能
总结
根本就是两个东西
抽象Abstract
一个修饰符,可以修饰类和方法
一旦修饰,变为虚无
抽象类abstract class
无法被 new
现象
1 2 3 public abstract class Cla { }
1 2 3!4 5 public class Dla { public void func() { new Cla(); }}
心态
有时一个类型太抽象, 仅仅为了消除代码冗余而出现
实际业务中, 并不会出现这个类型的对象
随堂检测
接口是抽象的
对
不对
抽象方法Abstract 函数
没有实现代码,只有声明
现象
1 2 3 public abstract class Cla { public abstract void func();}
心态
有时方法无法实现
有时方法会被所有子类覆盖掉, 并且所有子类都不调用 super, 实现了也没意义
abstract 相关规则
abstract 方法 和 abstract 类
一个结构里,如果有抽象的方法(严格来讲是,没有实现代码的方法),那么这个结构 必须是 abstract
abstract 和 接口
接口里的所有的方法都是抽象的,你写不写 abstract 都视为写了 abstract
接口 abstract 方法 与 实现类
实现类 欢乐 2 选 1
实现所有方法
没有实现所有方法,类声明为 abstract
父类 abstract 方法 与 子类
子类 欢乐 2 选 1
实现所有抽象方法
没有实现抽象方法,类继续声明为 abstract
抽象 与 接口 的对比
本质区别
接口是接口,为了创建新的访问权限
抽象类,还是类,只是不能被new
资源
抽象类里,可能有属性、方法、抽象方法
接口里,只能有抽象方法
关系
类 是
接口 能
特殊情况
如果一个抽象类 里 都是抽象方法,
那么会跟接口还蛮像的。
但子类只能有一个父类,可以实现多个接口
final 修饰符
一旦修饰,不可改变
final 修饰变量
不可被二次赋值
final 修饰局部变量
第一次赋值后,不可被二次赋值
1 2!final int a = 3;a = 4;
final 修饰参数变量
接收参数后,函数内不可被二次赋值
1 2 3 4 5 6 7!8 public void run() { f(3); f(5);} public int f(final int a) { a = 4;}
final 修饰属性
可以在声明、或所有构造方法里赋值
赋值后,不可被二次赋值
1 2 3 4!5 6 public class Cla { private final int a = 1; public void func() { a = 3; }}
1 2 3 4 5 6 7!8 9 public class Cla { private final int a; public Cla () { a = 2; } public void func() { a = 3; }}
final 修饰方法
方法不能被覆盖
从而阻止多态导致的行为改变
1 2 3 4 5 public class Cla { public final void func() { }}
1 2!3 4 5 public class Dla extends Cla { public void func() { }}
随堂检测
接口里的方法 可以标记为 final
对
不对
final 修饰类
类不能被继承
1 2 3 public final class Cla { }
1!2 3 public class Dla extends Cla { }
随堂检测
Object class 是 final 的
对
不对
接口 可以标记为 final
对
不对