首先我们要认识到:多态和接口都是为了增强程序的复用性而出现的。
我们先了解一下两者的特点、要求之后,再通过实际操作来增进理解
实现多态需要的条件:
- 必须在继承体系下;
- 子类必须要对父类中的方法进行重写
- 通过父类的引用调用重写方法
接口的特性:
- 接口不能被实例化
- 接口中的方法不能有具体的实现(JDK8后可以使用default来实现方法)
- 接口中不存在构造方法
- 接口需要被类(通过关键字implements)实现
- 接口被类实现后需要重写抽象方法
有两点让我印象深刻的对比之处我要点出来:
a、接口在被一个类实现后,要通过调用这个类才能访问;在多态中,父类被子类继承后,通过在”执行类“中发生”向上转型“,实例化子类后方可”通过父类的引用调用重写方法“
b、在多态中不能”多继承“,即一个子类只能有一个父类;但是在接口中,一个类可以有多个接口
现在我们来通过一个程序加深理解:
先使用多态的方法来实现程序!然后我们再来看看如果使用接口的话会怎么样!
abstract class BattleField1{
String Corps = "薯条";//抽象出来 兵种
String Arms;//抽象出来 武器
public BattleField1(String s,String t){ //父类的构造方法
System.out.println("装备着" + t + "的" + s + "已部署");
}
public abstract void Action(); //抽象方法连代码块({})都不能有!!!
}
抽象出来子类中的共同点,实现”程序复用“
例如:战地风云一中的”兵种“、”武器“、”行为“,这些特点是共有的,每个子类都要用
接下来我们写一个子类来继承这个抽象类
class Assault extends BattleField1{
public Assault(String Corps,String Arms){ //子类中的构造方法
super(Corps,Arms); //帮助父类实现构造方法并传参
this.Corps = "Pro"; //对父类中的成员变量赋值
}
@Override
public void Action() { //在子类中重写父类的方法时,前者的访问权限要大于后者
System.out.println(Corps + "正在进攻A点!!!");
}
}
class Medic extends BattleField1{
public Medic(String Corps,String Arms){ //子类中的构造方法
super(Corps,Arms);
this.Corps = "萨尼铁塔";
}
@Override
public void Action() {
System.out.println(Corps + "正在救人!!!");
}
}
接下来写一个”执行类“来调用子类中的方法
public class Polymorphism {
public static void main(String[] args) {
BattleField1 game = new Assault("突击兵","SMG-08");
//发生了“向上转型”。并且实例化了一个子类对象
game.Action(); //通过父类引用调用子类中的重写方法
BattleField1 game02 = new Medic("医疗兵","针筒");
game02.Action();
}
}
执行结果如下
但是战场上的士兵会有多种相同的行为:进攻、驾驶载具等,而这些行为不止一个,如果为了复用代码的话,使用继承肯定是不行的(因为不可多继承)。这时就使用接口——有了某个接口的所有对象都可以调用接口中的方法
接下来试试使用接口,老套路,先写一个抽象父类
abstract class BattleField1{
String Corps = "突击兵";//抽象出来 兵种
String Arms;//抽象出来 武器
public BattleField1(String s,String t){ //父类的构造方法
System.out.println("装备着" + t + "的" + s + "已部署");
}
}
写各种接口
interface IRunning{//跑
public abstract void Running();
}
interface IAttack{//进攻
public abstract void Attack();
}
interface IHealthy{//身体状态
public abstract void Healthy();
}
interface IDriving{//驾驶
public abstract void Driving();
}
写一个子类来实现这些接口并继承父类
class Assult extends BattleField1 implements IAttack,IDriving,IHealthy,IRunning{
//注意!继承写在接口前面!!!
public Assult(String s, String t) {
super(s, t);
}
//重写接口中的方法
@Override
public void Running() {
System.out.println(Corps + "正在突击!!!");
}
@Override
public void Attack() {
System.out.println(Corps + "正在进攻!!!");
}
@Override
public void Healthy() {
System.out.println(Corps + "血量健康");
}
@Override
public void Driving() {
this.Corps = "Pro";
System.out.println(Corps + "抢到了战争巨兽!!!");
}
}
写一个“执行类”来调用方法
public class Interfacee {
public static void Run(IRunning iRunning){
iRunning.Running();
}
public static void Drive(IDriving driving){
driving.Driving();
}
public static void main(String[] args) {
Run(new Assult("突击兵","M1917"));
//这里发生了向上转型!实例化一个Assult对象,并把这个对象传参给上面的Run方法
Drive(new Assult("支援兵","扳手"));
}
}
(从调用方法这点上来说,多态是发生向上转型,然后使用父类来调用子类中的重写方法;接口也是将子类转型成接口,然后通过接口调用子类中的构造方法)
执行结果如下:
写在最后:这篇文章是答主遇到“继承于接口的异同点”这个问题后的一个总结,代表着答主对于这个问题的初步认识。期待大家在评论区补充和纠正更多内容!!!