本篇来谈谈 Java 的抽象类和接口。
曹操在《短歌行》中为杜康酒打过一个价值一亿个亿的广告——“何以解忧,唯有杜康”,我替曹操感到惋惜的是他本人并不会收到这笔不菲的代言费。想一想,要是三国时期的明星人物们有这个代言意识的话,保证各家的军费收入会多出来一个重量级的来源。
不过,酒真的能解忧吗?我不大敢相信。李白就曾质疑过:“举杯消愁愁更愁,抽刀断水水更流。”我和李白持相同的观点,酒啊,真的不容易解忧,但绝对可以增加作者莫名的写作冲动。
我在写本篇之前就小酌了一杯,一不小心激发了我强烈的创作欲望。不过我要奉劝各位,寒冬之际,如果遇到烦心事,千万别肆意地追求一醉方休,万事要懂得适可而止。
01、 抽象类
一种比较苍白的说法是:在 Java 中,通过关键字 abstract 定义的类叫做抽象类。Java 是一门面向对象的语言,因此所有的对象都是通过类来描述的;但反过来,并不是所有的类都是用来描述对象的,抽象类就是其中的一种。
以下示例展示了一个简单的抽象类:
// 个人认为,一名教练必须攻守兼备 abstract class Coach { public abstract void defend(); public abstract void attack(); }
在一个抽象类中,至少有一个抽象方法(通过关键字 abstract 定义的方法,并且没有方法体,如上例中的 defend() 方法和 attack() 方法),否则就没有必要称之为抽象类。需要注意的是,抽象类是不能实例化的! 它需要被一个子类继承,就像以下示例那样。
abstract class Coach { public abstract void defend(); public abstract void attack(); } class Hesai extends Coach { @Override public void defend() { System.out.println("防守赢得冠军"); } @Override public void attack() { System.out.println("控球是把双刃剑"); } } public class Demo { public static void main(String[] args) { Coach moliniao = new Hesai(); moliniao.defend(); moliniao.attack(); } }
我们都知道,一个好的教练,必须攻守兼备,但每个教练的进攻理念和防守理念不尽相同。因此,我在教练这个抽象类(Coach)中定义两个抽象方法,一个进攻(attack)一个防守(defend),这两个方法的具体实现都要由抽象类的子类确定,抽象类本身并不负责。
我们也都知道,何塞·穆里尼奥是足球界的*教练。他是我最爱的足球教练,没有之一。尽管他在曼联的失败有他自身的原因,但我依然崇拜他,因为:“请不要说我傲慢,因为我只是实话实说,我是欧洲冠军,因此我并非籍籍无名,而是特殊的一个!”他是固执的反控球主义者,坚信控球是把双刃剑,防守赢得冠军。
好了,对于抽象类我们简单总结一下:
1、抽象类不能被实例化。
2、抽象类应该至少有一个抽象方法,否则它没有任何意义。
3、抽象类中的抽象方法没有方法体。
4、抽象类的子类必须给出父类中的抽象方法的具体实现,除非该子类也是抽象类。
02、 接口
我们知道,有抽象方法的类被称为抽象类,也就意味着抽象类中还能有不是抽象方法的方法。这样的类就不能算作纯粹的接口,尽管它也可以提供接口的功能——只能说抽象类是普通类与接口之间的一种中庸之道。
接口(英文:Interface),在 Java 中是一个抽象类型,是抽象方法的集合;接口通过关键字 interface 来定义。接口与抽象类的不同之处在于:
1、抽象类可以有方法体的方法,但接口没有。
2、接口中的成员变量隐式为 static final,但抽象类不是的。
3、一个类可以实现多个接口,但只能继承一个抽象类。
以下示例展示了一个简单的接口:
// 隐式的abstract interface Coach { // 隐式的public void defend(); void attack(); }
实现一个接口需要用到关键字 implements,它表示:“我这个类遵从了接口的协议,如果你想使用我,看接口就行了,具体实现不用关心。”
03、 实现多个接口
在现实生活中,何塞·穆里尼奥不止是一名足球教练,他还是一个值得被尊重的英雄——凭借自身的努力,他从一名籍籍无名的跟班翻译,逐渐蜕变为一名家喻户晓的*教练。
如果要在程序的世界里体现何塞·穆里尼奥的多重角色,就可以使用接口,就像以下示例展示那样。