普通类和抽象类
平时使用的哪些是普通类?
类本身是一种抽象的数据类型,是对某一事物的整体描述和定义, 我们平时new出来的对象, 就是通过在普通类的模版上产生的对象.
类中包含静态的属性(属性)和动态的行为(方法)
抽象类是在普通类的基础上又抽象了一些.
那么,
抽象类是什么?
抽象类: 如果类中包含抽象方法(使用abstract修饰的方法),那么这个类就是抽象类, 必须在类前面加上abstract修饰符;
但如果类中没有抽象方法, 类的前面还是加了abstract, 那这也是一个抽象类, 是一个挺蛋疼的抽象类
抽象方法: 只有方法的声明, 没有方法的实现, 具体的实现交给子类.
抽象类是不可以通过new的方法构造的, 但是抽象类可以有构造器
抽象类作为某个继承者的父类, 当实例化子类时,父类就会初始化.
继承了抽象类的子类通过super()或者super(参数…)来调用抽象类中的构造方法
抽象类不能直接实例化, 内部的抽象方法又没有具体的实现,那,
抽象类的意义何在?
最主要的作用就是方便维护和重用
- 可以把类与类之间 相同的属性和方法进行抽象, 或者对子类进行一些约束, 这样方便代码和程序的维护
举一个栗子, 学校招新生, 有"小学部"和"初中部"两个类, 这两个对象都是从"学校部门"这个类继承而来的, 每个类有公有的属性(学生数量, 年级数量, 教师数量等),这些相同的属性在抽象类"学校部门"中定义.
如果想修改公有属性,只需要在抽象类中修改就好了,不需要分别对子类进行修改
如果想在"学校部门"中修改某个信息, 会受到父类的限制, 这样也会对一些东西进行统一的限制.
- 当一个相似的类产生时,只要实现该抽象类,就可以获得抽象类的属性和方法
这是学校新开了一个"高中部", 如果没有"学校部门"这个抽象类,就需要将所有的属性和方法重新写一遍; 但是如果有抽象类,就可以直接继承这个抽象类, 使用个公有的属性, 仅需对自己独有的属性和方法进行补充就可以了.
抽象类怎么使用?
子类和父类 有一种 == “is a” == 的继承关系, 使用抽象类, 需要有一个相对没那么抽象的子类继承他.
抽象类不能使用new创建出对象, 生来是用来让子类继承的;
继承使用extends继承,但是extends具有局限性,是单继承,无法继承多个(儿子只能有一个爸爸)
抽象方法只有方法的声明, 没有方法的实现, 是用来让子类实现的.
接口
接口是什么
interface, 好像SDK中的API, java中的接口是可以直接供别人调用的方法,如果说抽象类是对一类事物进行抽象的话,接口就是对行为(方法)的抽象
接口代表一种特定的行为,不同的类可以根据各自的需要实现某个接口
接口中可以有属性和方法,属性只能使用public static final修饰(默认如此), 方法只能使用public abstract修饰(默认如此)
接口中所有的方法不能有具体的实现,必须全部都是抽象方法,和上面相比下来,抽象类还有写点可以实现的方法的自由,接口则代表了一种极端的抽象,我们使用里面的方法,而里面的所有方法都是抽象的.
接口可以理解为对象之间互相通信的协议, 接口中抽象方法的实现还是要看派生类
一个类实现了一个接口, 就相当于翻译成"如果你是… 你就必须能… ", 类是否实现接口是"有没有"的关系
使用接口就避免了extends的问题, 一个类可以实行多个接口
抽象类和接口的区别
项目 | 抽象类 | 接口 |
---|---|---|
方法 | 可以存在抽象方法,也可以存在方法的实现 | 只存在抽象方法 |
成员变量 | 可以包含各种类型的成员变量(属性) | 只可以是public abstract类型的成员变量 |
能否有静态代码块 | √ 可以有 | × 不能有 |
- | 模板式设计: 更改公共内容只需要更改抽象类就好了 | 辐射式设计: 接口变更,实现这个接口的类也必须变更 |
门和警报的例子: 现在门拥有open()和close()两个方法,分别通过抽象类和接口定义门:
// 抽象类
abstract class Door {
public abstract void open();
public abstract void close();
}
// 接口
interface Door{
public abstract void open();
public abstract void close();
}
如果取名为Door,是定义为接口好呢?还是定义为类好呢?
门是一个事物,而不是一个行为,所以门定义为抽象类比较好,抽象类中包含两个方法, open()和close(), 也就是门的共性的固有方法
现在, 我们想考虑一个报警功能alarm(), 应该怎么写?
如果将alarm()放到抽象类里,是不行的,因为不是所有门都有报警功能,alarm()并不是公有的属性
应该将alarm()重新设置成一个接口, 里面包含alarm()方法,
不同的门继承抽象类, 具备抽象类中公有的属性, 有的门类具有报警功能, 那么就实现alarm()接口,没有的话就不实现.
interface Alram {
void alarm();
}
abstract class Door {
void open();
void close();
}
class AlarmDoor extends Door implements Alarm {
void oepn() {
//....
}
void close() {
//....
}
void alarm() {
//....
}
}
参考
https://blog.csdn.net/qdh186/article/details/79704852
https://www.cnblogs.com/dolphin0520/p/3811437.html