1 什么是抽象类
我们都知道类是抽象的
,对象是具体的
。那抽象类是什么玩意?是比抽象的类还要抽象的类叫抽象类?
其实可以这样理解。
我们都知道如果一些对象具有一些相同的特征,我们可以把这些相同的特征抽取出来放到一个类里面。
比如李白、杜甫、白居易都属于诗人类
,鲁迅、巴金、钱钟书都属于作家类
。
而把诗人类、作家类相同的特征抽取出来,再往上一层都属于人类
,人类其实就是抽象类
。
你可能还是有点懵逼,一定要看到最后。
2. 抽象类的定义和使用
2.1 抽象类和抽象方法
-
- 用 abstract 关键字修饰的类是抽象类。
-
- 抽象类中用 abstract 修饰的方法是抽象方法。
-
- 抽象方法没有方法体。
例如:
// 抽象动物类
public abstract class Animal {
// 名字
String name;
// 抽象方法
abstract void eat();
}
2.2 抽象类无法创建对象
从上面图中我们知道类可以实例化对象,把一些类提取相同的特征往上抽象一层是
抽象类
。
类实例化为对象是从上往下,而抽象类的下一层还是类。类只能实例化对象,不能实例化类,所以抽象类不能创建对象,只能被子类继承。
但是,抽象类可以有构造方法:
//诗人类
public abstract class Poet {
// 构造方法
public Poet() {
}
}
你可能会说这不扯淡吗?构造器不就是用来创建对象的?
其实抽象类中的构造方法主要是为了创建子类时初始化属性用
的。
我们都知道,子类继承父类之后,创建子类对象的时候默认会先调用父类的构造方法。例如:
//诗人类
public abstract class Poet {
String name;
// 父类构造方法
public Poet() {
System.out.println("父构造器被调用了");
}
}
// 五言诗人类
public class FivePoet extends Poet{
}
public class AbstractTest {
public static void main(String[] args) {
FivePoet fivePoet = new FivePoet();
System.out.println(fivePoet.name);
}
}
运行结果:
如果父类没有给属性赋默认值,那么子类在继承父类之后,获取的属性值也是空的,例如上面打印的 name 值为 null。那么父类就可以在构造方法里面为属性赋值,例如:
//诗人类
public abstract class Poet {
String name;
// 父类构造方法
public Poet(String name) {
this.name = name;
System.out.println("父构造器被调用了");
}
2.3 抽象方法只能出现在抽象类中
如果一个类中含有抽象方法,那么这个类必须定义成抽象类。
下面才是正确的写法:
//诗人类
public abstract class Poet {
// 抽象方法没有方法体,只用提供声明
public abstract void write();
}
2.4 抽象类中可以没有抽象方法
抽象类中可以不用设置抽象方法,设置的普通方法必须要有方法体。
//诗人类
public abstract class Poet {
// 普通方法
public void read(){
System.out.println("诗人喜欢读书");
}
}
2.5 抽象类的子类必须重写抽象方法
如果一个抽象类声明了抽象方法,那么他的子类必须重写这个抽象方法。
// 诗人类
public abstract class Poet {
// 抽象方法没有方法体,只用提供声明
public abstract void write();
// 普通方法
public void read(){
System.out.println("诗人喜欢读书");
}
}
抽象类的子类可以是抽象类,也可以不是抽象类。
2.6 抽象类不能被 final 修饰
因为抽象类设计的初衷就是为了让子类继承的,而 final 修饰的类不能被子类继承,所以 abstract 和 final 不能一起使用,俩人是冤家。
2.7 抽象方法不能被 final 修饰
子类继承了抽象类必须要实现抽象的方法,而 final 修饰的方法不能被重写,所以 abstract 和 final 不能一起使用,俩人是冤家。
3. 理解抽象类
上面讲了那么多可能还是有些人不理解抽象类的用处。
你说抽象类是专门用来继承的,那普通类也可以被继承啊,普通类的方法也可以被子类实现啊,为什么还要专门搞个抽象类?那不还是“脱裤子放屁,多此一举吗?”
子类继承了一个普通类可以不用实现父类的方法,但是抽象类的核心就在:继承抽象类的子类必须
实现抽象方法。
必须是什么意思?是强制性的,是必须要遵守的规范!
就像加盟店必须要挂总店的招牌,外设要想被电脑识别必须要实现 USB 接口标准,这就是规范!
所以在开发过程中,如果遇到子类必须重写父类的方法的场景,可以用抽象类。
其实抽象类是为后面要学的接口
做铺垫的,诸位看官欲知详情,可以进一步说话,我们在接口那篇文章见。