抽象

抽象类

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类

1
2
3
修饰符 abstract class  类名{
//类的成员
}

抽象方法

分析事物时,发现了共性的内容,就出现向上抽取,但是如果父类的方法功能与子类不同,那么这时就不抽取方法主体,这样抽取出来的方法就是抽象方法

1
修饰符 abstract 返回值类型 方法名(参数列表);

使用 abstract 关键字修饰类,该类就是抽象类,不允许实例化(如果非要实例化,可以通过多态的形式创建,也就是父类引用指向子类对象)

使用 abstract 关键字修饰方法,该方法就成了抽象方法,抽象方法只包含一个方法名,而没有方法体

抽象类的成员特点

1
2
3
4
5
6
7
8
9
10
1. 成员变量:
● 可以是一般变量
● 也可以是常量

2. 成员方法:
● 可以是一般方法
● 也可以是抽象方法

3. 构造方法:
有,目的是为了方便子类进行初始化的

结论:抽象类中除了可以定义抽象方法以外,其余的定义和普通的类是一样的

抽象类总结规定

  • 抽象类不能被实例化。只有抽象类的非抽象子类可以创建对象
  • 抽象类中不一定包含抽象方法,但是如果一个类包含抽象方法,那么该类必须是抽象类
  • 抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现
  • 构造方法,类方法(用 static 修饰的方法)不能声明为抽象方法
  • 抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class Test1 {
public static void main(String[] args) {
Animal cat = new Cat();
cat.eat();
}
}

abstract class Animal {
/**
* 共性方法抽取出来
*/
public abstract void eat();
}

class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}

class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃肉");
}
}

抽象类和接口的区别

接口的设计目的,是对类的行为进行约束(更准确的说是一种<有>约束,因为接口不能规定类不可以有什么行为),也就是提供一种机制,可以强制要求不同的类具有相同的行为。它只约束了行为的有无,但不对如何实现行为进行限制。对“接口为何是约束”的理解,我觉得配合泛型食用效果更佳。

而抽象类的设计目的,是代码复用。当不同的类具有某些相同的行为(记为行为集合 A),且其中一部分行为的实现方式一致时(A 的非真子集,记为 B),可以让这些类都派生于一个抽象类。在这个抽象类中实现了 B,避免让所有的子类来实现 B,这就达到了代码复用的目的。而 A 减 B 的部分,留给各个子类自己实现。正是因为 A-B 在这里没有实现,所以抽象类不允许实例化出来(否则当调用到 A-B 时,无法执行)。

参考

接口和抽象类有什么区别? - 阿法利亚的回答 - 知乎