## Java编程那些事儿68——抽象类和接口(一)
陈跃峰
出自:[http://blog.csdn.net/mailbomb](http://blog.csdn.net/mailbomb)
### 8.9 抽象类和接口
在实际的项目中,整个项目的代码一般可以分为结构代码和逻辑的代码。就像建造房屋时,需要首先搭建整个房屋的结构,然后再细化房屋相关的其它的结构,也像制造汽车时,需要首先制作汽车的框架,然后才是安装配件以及美化等工作。程序项目的实现也遵循同样的道理。
在项目设计时,一个基本的原则就是——“设计和实现相分离”。也就是说结构代码和逻辑代码的分离,就像设计汽车时只需要关注汽车的相关参数,而不必过于关心如何实现这些要求的制作。程序设计时也是首先设计项目的结构,而不用过多的关系每个逻辑的代码如何进行实现。
前面介绍的流程控制知识,主要解决的是逻辑的代码的编写,而类和对象的知识,则主要解决结构代码的编写。那么还有一个主要的问题:如何设计结构代码呢?这就需要使用下面介绍的抽象类和接口的知识了。
#### 8.9.1 抽象类
抽象类(Abstract Class)是指使用abstract关键字修饰的类,也就是在声明一个类时加入了abstract关键字。抽象类是一种特殊的类,其它未使用abstract关键字修饰的类一般称作实体类。例如:
~~~
public abstract class A{
public A(){}
}
~~~
抽象方法(Abstract Method)是指使用abstract关键字修饰的方法。抽象方法是一种特殊的方法,其它未使用abstract关键字修饰的方法一般称作实体方法。
public abstract void test();
抽象类和实体类相比,主要有以下两点不同:
1. 抽象类不能使用自身的构造方法创建对象(语法不允许)
例如下面的语法是错误的:
A a = new A();
但是抽象类可以声明对象,例如下面的代码是正确的:
A a;
A a1,a2;
只是声明出的对象默认都是null的,无法调用其内部的非静态属性和非静态方法。
说明:抽象类可以使用子类的构造方法创建对象。
1. 抽象类内部可以包含任意个(0个、1个或多个)抽象方法
抽象类内部可以包含抽象方法,也可以不包含抽象方法,对于包含的个数没有限制。而实体类内部不能包含抽象方法。
在抽象类内部,可以和实体类一样,包含构造方法、属性和实体方法,这点和一般的类一样。
抽象方法和实体方法相比,主要有以下几点不同:
2. 抽象方法没有方法体
也就是说在声明抽象方法时,不能书写方法体的{},而只能以分号结束方法。下面是实体方法和抽象方法声明的比较:
抽象方法声明:
~~~
public abstract void test(int a);
~~~
实体方法声明:
~~~
public void test(int a){
方法体
}
~~~
3. 抽象方法所在的类必须为抽象类
也就是说,如果抽象方法声明在一个类内部,则该类必须为抽象类。(说明:抽象方法也可以出现在接口内部,这个将在后续进行介绍)。
这样,在继承时,如果继承的类是抽象类,而该抽象类中还包含抽象方法时,则该子类必须声明成抽象类,否则将出现语法错误。如果子类需要做成实体类的话,则必须覆盖继承的所有抽象方法。这个是抽象类最核心的语法功能——强制子类覆盖某些方法。
介绍了这么多抽象类和抽象方法的知识以后,那么抽象类有什么用途呢?
抽象类的用途主要有两个:
1. 严禁直接创建该类的对象
如果一个类内部包含的所有方法都是static方法,那么为了避免其它程序员误用,则可以将该类声明为abstract,这样其它程序员只能使用类名.方法名调用对应方法,而不能使用对象名.方法名进行调用。这样的类例如API中的Math类
说明:配合final关键字使用,将必须该类被继承,这样将获得更加完美的效果。
2. 强制子类覆盖抽象方法
这样可以使所有的子类在方法声明上保持一致,在逻辑上也必须将方法的功能保持一致。例如游戏中设计类时,设计了怪物类以及相关的子类,每个怪物类都有移动方法,但是每种怪物的移动规则又不相同,这样通过使每个怪物类的移动方法的声明保持一致,方便调用。可以参看前面多态部分的介绍获得更多的关于调用统一知识。
这是抽象类最主要的用途。就像现实社会中,各种银行网点保持统一的装修风格,各种快餐店(肯德基、麦当劳等)保持统一的装修甚至风味,这样便于生活中的识别。通过让存在继承关系的类中功能一样(但是内部实现规则不同)的方法声明成一样的,方便多态的使用。
那么什么时候在设计时使用抽象类呢?这个问题参看一下抽象类的用途自然就知道了。关于抽象类的知识先介绍这么多,下面介绍接口的知识,最终将对抽象类和接口进行一下比较。
- 前言
- (1)序言
- (2)程序设计是什么?
- (3)你适合学习程序设计吗?
- (4)如何学好程序设计?
- (5)程序设计介绍小结
- (6)计算机软件基本概念
- (7)进制的概念
- (8)计算机内部的数据表达
- (9)网络编程基础
- (10)Java语言简介
- (11)JDK的获得、安装和配置
- (12)第一个HelloWorld程序
- (13)Eclipse基本使用
- (14)Eclipse基础使用进阶
- (15)如何学好Java语法
- (16)代码框架、关键字和标识符
- (17)基本数据类型
- (18)变量和常量
- (19)数据类型转换
- (20)空白、语句结束和注释
- (21)算术运算符
- (22)比较运算符
- (23)逻辑运算符
- (24)赋值运算符
- (25)位运算符
- (26)移位运算符
- (27)其它运算符
- (28)运算符优先级
- (29)表达式
- (30)流程控制基础
- (31)if语句语法(1)
- (32)if语句语法(2)
- (33)if语句语法(3)
- (34)switch语句语法
- (35)while语句语法
- (36)do-while语句语法
- (37)for语句语法
- (38)break和continue语句
- (39)流程控制综合示例1
- (40)流程控制综合示例2
- (41)流程控制综合示例3
- (42)流程控制综合练习
- (43)数组概述
- (44)数组基础语法
- (45)数组使用示例1
- (46)数组使用示例2
- (47)数组使用示例3
- (48)多维数组基础
- (49)多维数组使用示例1
- (50)多维数组使用示例2
- (51)多维数组练习
- (52)方法声明
- (53)方法声明示例
- (54)方法调用
- (55)方法重载和参数传递
- (56)方法练习
- (57)面向对象基础
- (58)类(一)
- (59)类(二)
- (60)对象
- (61)面向对象设计方法和面向对象特性(一)
- (62)继承(二)
- (63)多态性
- (64)访问控制符、修饰符和其它关键字
- (65)static修饰符
- (66)final修饰符
- (67)this和super
- (68)抽象类和接口(一)
- (69)抽象类和接口(二)
- (70)抽象类和接口(三)
- (71)内部类简介
- (72)包的概念
- (73)JDK文档使用
- (74)java.lang包介绍1
- (75)String类使用
- (76)StringBuffer类和System类
- (77)包装类
- (78)时间和日期处理
- (79)Random随机处理
- (80)集合框架简述
- (81)异常处理概述
- (82)异常处理语法1
- (83)异常处理语法2
- (84)IO简介
- (85)IO类体系
- (86)文件操作之File类使用
- (87)文件操作之读取文件
- (88)文件操作之写文件
- (89)读取控制台输入
- (90)装饰流使用1
- (91)装饰流使用2
- (92)IO使用注意问题
- (93)多线程基础
- (94)多线程实现方式1
- (95)多线程实现方式2
- (96)多线程使用示例1
- (97)多线程使用示例2
- (98)多线程问题及处理1
- (99)多线程问题及处理2
- (100)多线程问题及处理3
- (101)网络编程概述
- (102)网络编程技术1
- (103)网络编程技术2
- (104)网络编程技术3
- (105)网络编程技术4
- (106)网络编程技术5
- (107)网络协议概念
- (108)网络编程示例1
- (109)网络编程示例2
- (110)网络编程小结