简介
上几篇一直在说面向对象理论中的抽象类的一些具体应用。今天我来说说面向对象理论中另一个关键的东西。接口。抽象类是类,接口是特殊的抽象类。为什么要用那么多时间来研究抽象类和接口呢?因为只有这二个理论我们掌握了、理解了。会用了。才能大大提高程序的可扩展性和可维护性。以后在学什么设计模式也是一层窗户纸一捅就破。
概念
Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
两种含义:(概念摘录于百度百科)
- Java接口,Java语言中存在的结构,有特定的语法和结构;
- 一个类所具有的方法的特征集合,是一种逻辑上的抽象。前者叫做“Java接口”,后者叫做“接口”。
我个人理解,接口=>口号 相关于口号 具体的工作由下面的人来完成
例如:某领导在开会时对手下的人说,我们公司想要开发一个跑步时计算卡罗里的手环,最终结果可在手机上显示出来。手机与蓝牙连接方式采用蓝牙技术。
这就是口号。具体的手机蓝牙如何和手环相连接,数据如何显示在手机上等等的技术问题,领导不关。这些个工作主要由手下的人去做。从面向对象理论上来讲这就是接口。
接口,英文称作interface,在软件工程中,接口泛指供别人调用的方法或者函数。从这里,我们可以体会到Java语言设计者的初衷,它是对行为的抽象。在Java中,定一个接口的形式如下:
语法格式:
[public] interface Person { abstract void Study() throws Exception;//抽象方法,具体的功能由子类来完成 }
大家是不是觉得,接口和前面讲的抽象类很像。是的。接口和抽象类。这两者有太多相似的地方,又有太多不同的地方。很多人在初学的时候会以为它们可以随意互换使用,但是实际则不然。
抽象类是类,接口是接口
简单点说就是:抽象类的子类不能再继承其他的类,可以实现多个接口.因为java是单继承的.
讲接口的时候离不开抽象类。如果单独的去讲,失去了其本质的内容。有的培训中心的老师在讲解的时候,是单独举例讲解的。很坑人。
下面我以一个例子来说明在实际开发中接口和抽象类是如何使用的。
记住面向对象编程,其实就是面向接口编程。Java是单继承的,但是可以实现多个接口。这就是Java代码的神奇之处。很多的设计模式也是利用了这一点。
举例子分析:
狗、兔子、鱼 这三个动物为例
按照我前面所讲的。大家很快就能把抽象类设计出来。如果还不能也没有关系。在把我们所讲结合百度一起在看一遍。
1 public abstract class Animal { 2 public abstract void Breathing();//呼吸 3 public abstract void Eat();//吃 4 public abstract void Swimming();//游泳 5 }
抽象类有了。我们现在设计 狗、兔子、鱼这三个子类。
1 public class Dog extends Animal { 2 3 @Override 4 public void Breathing() { 5 System.out.print("呼吸空气的感觉真好"); 6 } 7 8 @Override 9 public void Eat() { 10 System.out.print("主人给我骨头吃了"); 11 } 12 13 @Override 14 public void Swimming() { 15 System.out.print("游泳的感觉真好"); 16 } 17 }
1 public class Fish extends Animal { 2 3 @Override 4 public void Breathing() { 5 System.out.print("呼吸空气的感觉真好"); 6 } 7 8 @Override 9 public void Eat() { 10 System.out.print("我在吃东西"); 11 } 12 13 @Override 14 public void Swimming() { 15 System.out.print("水中的感觉真好"); 16 } 17 }
最后是兔子类。
1 public class Rabbit extends Animal { 2 3 @Override 4 public void Breathing() { 5 System.out.print("呼吸空气的感觉真好"); 6 } 7 8 @Override 9 public void Eat() { 10 System.out.print("胡萝卜真好吃"); 11 } 12 13 @Override 14 public void Swimming() { 15 System.out.print("5555555555555,我不会游泳"); 16 } 17 }
发现问题了吧,兔子不会游泳,因为是继承的关系。以后每一个动物不管会不会游泳都要重写那个Swimming方法。要知道不是每个动物都会游泳的。
怎么办。有人说在写一个游泳功能的类,让其继承。亲 Java只支持单继承,不支持多继承,但是可但是但可是呢?可以支持多接口。在这里我们不需要那么多的接口一个就够了。
先把抽象类的代码改一下
1 public abstract class Animal { 2 public abstract void Breathing();//呼吸 3 public abstract void Eat();//吃 4 }
那个游泳功能怎么办。我们单独写一个接口
1 public interface AnimalBehavior { 2 public abstract void Swimming();//游泳 3 }
那该怎么用呢?我们将上面的 狗、鱼的子类改一下
1 public class Dog extends Animal implements AnimalBehavior{ 2 3 @Override 4 public void Breathing() { 5 System.out.print("呼吸空气的感觉真好"); 6 } 7 8 @Override 9 public void Eat() { 10 System.out.print("主人给我骨头吃了"); 11 } 12 13 @Override 14 public void Swimming() { 15 System.out.print("游泳的感觉真好"); 16 } 17 }
1 public class Fish extends Animal implements AnimalBehavior { 2 3 @Override 4 public void Breathing() { 5 System.out.print("呼吸空气的感觉真好"); 6 } 7 8 @Override 9 public void Eat() { 10 System.out.print("我在吃东西"); 11 } 12 13 @Override 14 public void Swimming() { 15 System.out.print("水中的感觉真好"); 16 } 17 }
兔子类
1 public class Rabbit extends Animal { 2 3 @Override 4 public void Breathing() { 5 System.out.print("呼吸空气的感觉真好"); 6 } 7 8 @Override 9 public void Eat() { 10 System.out.print("胡萝卜真好吃"); 11 } 12 }
抽象类与接口的区别
Java接口和Java抽象类有太多相似的地方,又有太多特别的地方,究竟在什么地方,才是它们的最佳位置呢?把它们比较一下,你就可以发现了。
Java接口和Java抽象类最大的一个区别,就在于Java抽象类可以提供某些方法的部分实现,而Java接口不可以(就是interface中只能定义方法,而不能有方法的实现,而在abstract class中则可以既有方法的具体实现,又有没有具体实现的抽象方法),这大概就是Java抽象类唯一的优点吧,但这个优点非常有用。如果向一个抽象类里加入一个新的具体方法时,那么它所有的子类都一下子都得到了这个新方法,而Java接口做不到这一点,如果向一个Java接口里加入一个 新方法,所有实现这个接口的类就无法成功通过编译了,因为你必须让每一个类都再实现这个方法才行,这显然是Java接口的缺点。这个在我的另外一篇博客mapreduce 新旧API 区别中有提到类似的问题,在新的mapreduce api中更倾向于使用抽象类,而不是接口,因为这更容易扩展。原因就是上面划线部分所说的。
一个抽象类的实现只能由这个抽象类的子类给出,也就是说,这个实现处在抽象类所定义出的继承的等级结构中,而由于Java语言的单继承性,所以抽象类作为类型定义工具的效能大打折扣。在这一点上,Java接口的优势就出来了,任何一个实现了一个Java接口所规定的方法的类都可以具有这个接口的类型,而一个类可以实现任意多个Java接口,从而这个类就有了多种类型。(使用抽象类,那么继承这个抽象类的子类类型就比较单一,因为子类只能单继承抽象类;而子类能够同时实现多个接口,因为类型就比较多。接口和抽象类都可以定义对象,但是只能用他们的具体实现类来进行实例化。)
从第2点不难看出,Java接口是定义混合类型的理想工具,混合类表明一个类不仅仅具有某个主类型的行为,而且具有其他的次要行为。
结合1、2点中抽象类和Java接口的各自优势,具精典的设计模式就出来了:声明类型的工作仍然由Java接口承担,但是同时给出一个Java 抽象类,且实现了这个接口,而其他同属于这个抽象类型的具体类可以选择实现这个Java接口,也可以选择继承这个抽象类,也就是说在层次结构中,Java 接口在最上面,然后紧跟着抽象类,这下两个的最大优点都能发挥到极至了。这个模式就是“缺省适配模式”。在Java语言API中用了这种模式,而且全都遵循一定的命名规范:Abstract +接口名。(A extends AbstractB implements interfaceC,那么A即可以选择实现(@Override)接口interfaceC中的方法,也可以选择不实现;A即可以选择实现(@Override)抽象类AbstractB中的方法,也可以选择不实现)
继承是一个 "是不是"的关系,而 接口 实现则是 "有没有"的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比如鸟是否能飞(或者有没有飞行这个特点)
感悟
简单的业务设计起来容易,复杂的业务要想把其按面向对象理论方式进行设计。得需要一定的经验来我们对技术孜孜不倦的追求。和对业务的深入理解。软件开发不要以为就是编写代码。其实不然这里面充满的智慧和挑战。
如果你对你要开发的业务流程不熟悉。你设计模式学的再好,你也会感到无从下手。当你对业务熟悉了,设计模式也精通了。您一定是在那个领域中的领军人物。将来知深架构师这个头衔非你莫属。
声明如下:
- 学会用面向对象思想解决问题,是作为程序员一个良好的习惯。
- 技术无止境,学习无止境。我只是起到一个入门和抛砖引玉的作用。
- 因为本人有很多的工作要做。写这个主要是利用业余时间。难免代码有错误的地方。或文字上有错别字。还是这句话,写这些主要是教大家如何学习。理论掌握了,语言只是工具。谢谢大家在百忙之中观看此文。
- 文中代码实现,已经测试过:
- 我写的内容可以随便转载,欢迎大家转载。