本系列文章经补充和完善,已修订整理成书《Java编程的逻辑》,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接http://item.jd.com/12299018.html


基本概念

上节提到了一个概念,抽象类,抽象类是什么呢?顾名思义,抽象类就是抽象的类,抽象是相对于具体而言的,一般而言,具体类有直接对应的对象,而抽象类没有,它表达的是抽象概念,一般是具体类的比较上层的父类。

比如说,狗是具体对象,而动物则是抽象概念,樱桃是具体对象,而水果则是抽象概念,正方形是具体对象,而图形则是抽象概念。下面我们通过一些例子来说明Java中的抽象类。

抽象方法和抽象类

之前我们介绍过图形类Shape,它有一个方法draw(),Shape其实是一个抽象概念,它的draw方法其实并不知道如何实现,只有子类才知道。这种只有子类才知道如何实现的方法,一般被定义为抽象方法。

抽象方法是相对于具体方法而言的,具体方法有实现代码,而抽象方法只有声明,没有实现,上节介绍的接口中的方法就都是抽象方法。

抽象方法和抽象类都使用abstract这个关键字来声明,语法如下所示:

public abstract class Shape {
// ... 其他代码
public abstract void draw();
}

定义了抽象方法的类必须被声明为抽象类,不过,抽象类可以没有抽象方法。抽象类和具体类一样,可以定义具体方法、实例变量等,它和具体类的核心区别是,抽象类不能创建对象(比如,不能使用new Shape()),而具体类可以。

抽象类不能创建对象,要创建对象,必须使用它的具体子类。一个类在继承抽象类后,必须实现抽象类中定义的所有抽象方法,除非它自己也声明为抽象类。圆类的实现代码,如下所示:

public class Circle extends Shape {
//...其他代码 @Override
public void draw() {
// ....
}
}

圆实现了draw()方法。与接口类似,抽象类虽然不能使用new,但可以声明抽象类的变量,引用抽象类具体子类的对象,如下所示:

Shape shape = new Circle();
shape.draw();

shape是抽象类Shape类型的变量,引用了具体子类Circle的对象,调用draw方法将调用Circle的draw代码。

为什么需要抽象类?

抽象方法和抽象类看上去是多余的,对于抽象方法,不知道如何实现,定义一个空方法体不就行了吗,而抽象类不让创建对象,看上去只是增加了一个不必要的限制。

引入抽象方法和抽象类,是Java提供的一种语法工具,对于一些类和方法,引导使用者正确使用它们,减少被误用。

使用抽象方法,而非空方法体,子类就知道他必须要实现该方法,而不可能忽略。

使用抽象类,类的使用者创建对象的时候,就知道他必须要使用某个具体子类,而不可能误用不完整的父类。

无论是写程序,还是平时做任何别的事情的时候,每个人都可能会犯错,减少错误不能只依赖人的优秀素质,还需要一些机制,使得一个普通人都容易把事情做对,而难以把事情做错。抽象类就是Java提供的这样一种机制。

抽象类和接口

抽象类和接口有类似之处,都不能用于创建对象,接口中的方法其实都是抽象方法。如果抽象类中只定义了抽象方法,那抽象类和接口就更像了。但抽象类和接口根本上是不同的,一个类可以实现多个接口,但只能继承一个类。

抽象类和接口是配合而非替代关系,它们经常一起使用,接口声明能力,抽象类提供默认实现,实现全部或部分方法,一个接口经常有一个对应的抽象类。

比如说,在Java类库中,有:

  • Collection接口和对应的AbstractCollection抽象类
  • List接口和对应的AbstractList抽象类
  • Map接口和对应的AbstractMap抽象类

对于需要实现接口的具体类而言,有两个选择,一个是实现接口,自己实现全部方法,另一个则是继承抽象类,然后根据需要重写方法。

继承的好处是复用代码,只重写需要的即可,需要写的代码比较少,容易实现。不过,如果这个具体类已经有父类了,那就只能选择实现接口了。

我们以一个例子来进一步说明这种配合关系,还是用前面两节中关于add的例子,上节引入了IAdd接口,代码如下:

public interface IAdd {
void add(int number);
void addAll(int[] numbers);
}

我们实现一个抽象类AbstractAdder,代码如下:

public abstract class AbstractAdder implements IAdd {
@Override
public void addAll(int[] numbers) {
for(int num : numbers){
add(num);
}
}
}

这个抽象类提供了addAll方法的实现,它通过调用add方法来实现,而add方法是一个抽象方法。

这样,对于需要实现IAdd接口的类来说,它可以选择直接实现IAdd接口,或者从AbstractAdder类继承,如果继承,只需要实现add方法就可以了。这里,我们让原有的Base类继承AbstractAdder,代码如下所示:

public class Base extends AbstractAdder {
private static final int MAX_NUM = 1000;
private int[] arr = new int[MAX_NUM];
private int count; @Override
public void add(int number){
if(count<MAX_NUM){
arr[count++] = number;
}
}
}

小结

本节,我们谈了抽象类,相对于具体类,它用于表达抽象概念,虽然从语法上,抽象类不是必须的,但它能使程序更为清晰,减少误用,抽象类和接口经常相互配合,接口定义能力,而抽象类提供默认实现,方便子类实现接口。

在目前关于类的描述中,每个类都是独立的,都对应一个Java源代码文件,但在Java中,一个类还可以放在另一个类的内部,称之为内部类,为什么要将一个类放到别的类内部呢?

----------------

未完待续,查看最新文章,敬请关注微信公众号“老马说编程”(扫描下方二维码),从入门到高级,深入浅出,老马和你一起探索Java编程及计算机技术的本质。用心写作,原创文章,保留所有版权。

-----------

更多相关原创文章

计算机程序的思维逻辑 (13) - 类

计算机程序的思维逻辑 (14) - 类的组合

计算机程序的思维逻辑 (15) - 初识继承和多态

计算机程序的思维逻辑 (16) - 继承的细节

计算机程序的思维逻辑 (17) - 继承实现的基本原理

计算机程序的思维逻辑 (18) - 为什么说继承是把双刃剑

计算机程序的思维逻辑 (19) - 接口的本质

计算机程序的思维逻辑 (21) - 内部类的本质

Java编程的逻辑 (20) - 为什么要有抽象类?的更多相关文章

  1. Java编程的逻辑 (95) - Java 8的日期和时间API

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

  2. Java编程的逻辑 (94) - 组合式异步编程

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

  3. Java编程的逻辑 (92) - 函数式数据处理 (上)

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  4. 《Java编程的逻辑》 - 文章列表

    <计算机程序的思维逻辑>系列文章已整理成书<Java编程的逻辑>,由机械工业出版社出版,2018年1月上市,各大网店有售,敬请关注! 京东自营链接:https://item.j ...

  5. Java编程的逻辑 (11) - 初识函数

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  6. Java编程的逻辑 (13) - 类

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  7. Java编程的逻辑 (14) - 类的组合

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

  8. Java编程的逻辑 (15) - 初识继承和多态

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  9. Java编程的逻辑 (16) - 继承的细节

    ​本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...

随机推荐

  1. C#解析数组形式的json数据

    在学习时遇到把解析json数据的问题,网上也搜了很多资料才得以实现,记录下来以便翻阅. 1. 下载开源的类库Newtonsoft.Json(下载地址http://json.codeplex.com/, ...

  2. mysql 分组取每个组的前几名的问题

    select *from hotel_addition_orders awhere (select count(*) from hotel_addition_orders where hotel_or ...

  3. Spring Boot整合MyBatis(使用Spring Tool Suite工具)

    1. 创建Spring Boot项目 通过Spring Tool Suite的Spring Starter Project对话框,其实是把项目生成的工作委托http://start.spring.io ...

  4. 大数据高性能数据库Redis在Windows上的使用教程

    Redis学习笔记----Redis在windows上的安装配置和使用 Redis简介 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括s ...

  5. plsql批量导入sql文件

    背景:有时候在两个数据库之间导入导出数据,不可避免的需要进行sql文件的批量导入,一个个导入效率太低,所以可以考虑批量导入的办法进行导入. 操作步骤 1.假设有三个sql脚本,分别为aa.sql,bb ...

  6. 神奇:java中float,double,int的值比较运算

    float x = 302.01f;    System.out.println(x == 302.01); //false  System.out.println(x == 302.01f); // ...

  7. 稳定排序nlogn之归并排序_一维,二维

    稳定排序nlogn之归并排序_一维,二维 稳定排序:排序时间稳定的排序 稳定排序包括:归并排序(nlogn),基数排序[设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排 ...

  8. python数据分析美国大选项目实战(三)

    项目介绍 项目地址:https://www.kaggle.com/fivethirtyeight/2016-election-polls 包含了2015年11月至2016年11月期间对于2016美国大 ...

  9. mybatis入门基础----高级映射(一对一,一对多,多对多)

    阅读目录 一:订单商品数据模型 二.一对一查询 三.一对多查询 四.多对多查询 回到顶部 一:订单商品数据模型 1.数据库执行脚本 创建数据库表代码: CREATE TABLE items ( id ...

  10. Linux命令(八)Linux系统信息相关命令

    top: