本文的目的是讨论抽象类和接口的作用、示例和使用场景,这是我的理解和总结。对于接口和抽象类的更多概念性知识,你可以自己参考相关文档。

1. 抽象类及其作用

抽象类,顾名思义,即类的抽象。

当引入面向对象的概念时,我们知道类是客观事物的抽象,抽象类是类的进一步抽象。如何理解它们?

例如,我们定义了宝马、奔驰和奥迪三大类,并分别抽象出宝马、梅赛德斯-奔驰和奥迪这三类车辆,包括相关的属性和行为(即方法)。但我们知道,汽车具有一般属性和行为,如品牌、发动机、方向盘、轮胎、前向、后退、转向等。因此,我们可以进一步抽象出宝马、梅赛德斯-奔驰等汽车上的“汽车”类的抽象类,包括一般特征(属性和侧面)。Law)让宝马、奔驰、奥迪继承抽象类扩展汽车,它们具有汽车的一般特征,然后在抽象类的基础上定义自己的特殊属性和方法。

这里的 abstract class Car 即抽象类,可以看出,抽象类是用来捕捉子类的通用特性的,包括属性及行为

2. 接口及其作用

让我们看一下界面。如果我开发了一款叫Bote Royce的飞车,它的定义如下:

 1 class BoteRoyce extends Car {
 2     //...省略通用特性
 3
 4     /**
 5      * 可以飞
 6      */
 7     void fly() {
 8         System.out.println("假装会飞~");
 9     }
10 }

看起来没问题:

  • BoteRoyce extends Car:表达这是一辆汽车;
  • fly() 方法:体现这车可以飞。

但是,随着技术发展,出现了众多可以制造飞行汽车的厂商,难道每一个可以飞的汽车都去定义一个 fly() 方法?

心想这还不简单,在抽象类 Car 中定义一个抽象方法 abstract void fly() 让子类去实现,不就可以了吗?

不不不…并非所有的牛奶都被称为Trensu,不是所有的汽车都能飞。飞行不是汽车的一般特征。在Car中定义.()方法显然违反了使用抽象类捕获子类的一般特征的原则。

在这种场景下,解决方案之一就是使用接口,如下:

1 /**
2  * 飞行器接口
3  */
4 public interface Aircraft {
5     //定义抽象方法
6     void fly();
7 }

BoteRoyce 的定义修改如下:

 1 /*
 2  * 实现 Aircraft 接口,表示具备飞行器能力
 3  */
 4 class BoteRoyce extends Car implements Aircraft {
 5
 6     /**
 7      * 覆写接口方法,实现飞行能力
 8      */
 9     @Override
10     void fly() {
11         System.out.println("假装会飞~");
12     }
13 }

再有其他品牌的飞行汽车,都可以通过 extends Car implements Aircraft 实现飞行能力。

上述定义的 interface Aircraft 即为接口,我们通常使用接口对行为进行抽象

3. 接口和抽象类的区别

关于二者的区别,可以结合前面的例子,来加深理解。

抽象类是对类本质的抽象,表达的是 is a 的关系,比如:BMW is a Car。抽象类包含并实现子类的通用特性,将子类存在差异化的特性进行抽象,交由子类去实现。

而接口是对行为的抽象,表达的是 like a 的关系。比如:Bote-Royce like a Aircraft(像飞行器一样可以飞),但其本质上 is a Car。接口的核心是定义行为,即实现类可以做什么,至于实现类主体是谁、是如何实现的,接口并不关心。

4. 接口与抽象类的使用场景

熟悉Java的学生可能会质疑,通过重新提取CARE,可以实现上述接口的使用:

1 /**
2  * 会飞的汽车
3  */
4 abstract class FlyCar extends Car {
5
6     //定义抽象方法
7     public abstract void fly();
8 }

普通的汽车依然 extends Car,可以飞行的汽车 extends FlyCar 即可:

 1 /*
 2  * 继承 FlyCar,表示是可以飞行的汽车
 3  */
 4 class BoteRoyce extends FlyCar {
 5
 6     /**
 7      * 覆写抽象方法,实现飞行能力
 8      */
 9     @Override
10     public void fly() {
11         System.out.println("假装会飞~");
12     }
13 }

如果你也这么想,表示你 get 到了抽象类的点。不过话说回来,这样的话接口岂不是没有存在的意义了?

当然不是了。就 BoteRoyce 而言,如果你关心的是“飞行汽车”这个整体,那么定义抽象类 FlyCar 是个不错的选择;如果你关心的是汽车具备“飞行”的行为,那不妨继续沿用前面使用 Aircraft 接口的方案。

这与设计模式中的六条原则之一——RichterReplac.Principle——相一致,该原则规定对基类(抽象类或接口)的所有引用在使用其子类的对象时必须是透明的。也就是说,当您遵循这个原则时,您必须考虑您是关心“飞车”实体还是“飞车”行为,并将其作为基类来确定程序的可接受的子类对象。

同时,“接口隔离原则”指导我们,一个类对另一个类的依赖应该建立在最小的接口上。相比于抽象类 FlyCar,接口 Aircraft 能最大限度的减少对外暴露的接口,并隐藏细节,更符合这一原则。

因此,面向对象只是指导我们的编程,而不是规则和规则的想法。在实际的开发中,抽象类或接口的使用并非绝对受限,而是取决于您的业务场景和体系结构设计。

5. 最后

好了,这就是接口和抽象类的总结。你彻底理解了吗?

这一次,让你彻底明白接口及抽象类相关推荐

  1. java接口和抽象类的区别(经典面试题)

    java接口和抽象类的区别(经典面试题) 要了解接口和抽象类的区别,首先需要明白接口和抽象类的定义. 1.抽象类 包含抽象方法的类称为抽象类,但并不意味着抽象类中只能有抽象方法,它和普通类一样,同样可 ...

  2. JavaSE学习总结(六)——接口、抽象类、内部类

    一.不需要实例化的原因 看一个示例: package com.zhangguo.chapter5.s1;/**动物园*/ public class Zoo {public static void ma ...

  3. C#读书笔记之继承、接口与抽象类续

    C#读书笔记之继承.接口与抽象类 http://www.cnblogs.com/linjzong/articles/2717173.html 接下来说明最开始提出的问题:为什么要使用接口和抽象类? 刚 ...

  4. 【转载】接口和抽象类的区别 --相信你看完不会再混淆了

    原文地址:http://www.cnblogs.com/huihui-gohay/archive/2009/12/13/1623070.html 我想,对于各位使用面向对象编程语言的程序员来说,&qu ...

  5. java 接口是抽象类吗_我是如何理解Java抽象类和接口的

    在面试中我们经常被问到:Java中抽象类和接口的区别是什么?然后,我们就大说一通抽象类可以有方法,接口不能有实际的方法啦;一个类只能继承一个抽象类,却可以继承多个接口啦,balabala一大堆,就好像 ...

  6. java抽象类中的变量修饰符_菜鸟整理的三个权限修饰符与接口、抽象类的总结...

    static 静态变量 被static修饰的变量其实是一个全局变量. 当这个类被虚拟机第一次加载的时候,就会为该变量分配了内存空间. 当该类创建实例时,并不会生成对static变量的拷贝.而是多个该类 ...

  7. 什么时候使用接口?什么时候使用抽象?选择Java接口还是抽象类 (转)

    老帖了,但是还是想自己收录一下.最后也把自己对于这个问题的一些粗糙的理解记录下来. 在一个面向对象的系统中,系统的各种功能是由许许多多的不同对象协作完成的.在这种情况下,各个对象内部是如何实现自己的对 ...

  8. java接口和抽象类的区别和作用

    java接口和抽象类的区别和作用 接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明.一个类通过(implements)接口的方 ...

  9. 深入理解Java的接口和抽象类

    http://www.cnblogs.com/dolphin0520/p/3811437.html 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口 ...

最新文章

  1. log4j在eclipse上使用简介
  2. 数值分析上机题matlab线性方程组,数值分析上机实验报告 - 线性方程组部分实验题1...
  3. 021_jdbc-mysql入门
  4. SpringBoot启动banner更改
  5. 性能优化8--内存泄露
  6. js获取图片真实尺寸 - 代码篇
  7. C语言教程第六章:指针(2)
  8. AndroidStudio_安卓原生开发_Json解析报错_要注意这点---Android原生开发工作笔记141
  9. 普通函数被类引用为友元函数
  10. 经典算法(1)- 求1到N的质数
  11. 大华管理平台用户名_助力制造苏州紫光云引擎携手大华精密,共建精密机加数字化样板工厂...
  12. NeurIPS 2021 放榜!旷视研究院5篇接收论文亮点解读!
  13. c语言遍历算法的头文件,图优先遍历算法(C语言版).doc
  14. 根据userAgent获取浏览器/操作系统/设备类型等信息
  15. 物联网如何改变医疗保健行业
  16. Nature子刊:AI技术从零开始设计具有生物活性的蛋白质
  17. 读写超快的随身存储好物,设计也很漂亮,大华S809固态U盘上手
  18. 姚俊军:如何设计数据迁移方案
  19. 《乌合之众》——古斯塔夫·勒庞
  20. 电机编码器调零步骤_一种伺服系统零点校对的绝对值编码器调零方法与流程

热门文章

  1. nginx 的启动、停止与重启
  2. Android(java方法)上实现mp4的分割和拼接 (一)
  3. CodeForces 501B - Misha and Changing Handles
  4. 设计模式精髓—封装变化
  5. nginx+apache实现负载均衡+动静分离配置(编译安装)
  6. ibatis返回数据集映射举例
  7. 使用Ant编译Hadoop eclipse插件
  8. 部署Symantec Antivirus 10.0网络防毒服务器之三
  9. C#启动一个外部程序(1)-WinExec
  10. 思科修复运营商级路由器中的两个已遭利用漏洞