关于对抽象的一点理解
1 什么是抽象
1.1 关于多态
在面向对象编程中,多态是指一类事物有多种形态。比如A类,A-1和A-2都属于动物类,它们都有A类中公共的方法
由于多态的存在,每个子类都可以覆写父类的方法,例如下面的代码中子类1和2都覆写了父类中的某个方法:
在这里,假如我们要设计一款游戏名叫 Apax 的枪械游戏。在这款游戏中,我们的武器就是枪械,所以我们来为我们的游戏设计一个 Weapon
类,它代表所有枪械的父类:
1 | // 父类-武器 |
1.2 关于抽象
可以看到, WeaponAmmo
方法在子类中是覆写的父类的方法,并且父类也确实具有 WeaponAmmo
方法的实现。但是如果父类的方法本身不需要实现任何功能,仅仅是为了定义方法签名,目的是让子类去覆写它,那么,可以把父类的方法声明为抽象方法:
1 | class Weapon { |
把一个方法声明为 abstract
,表示它是一个抽象方法,本身没有实现任何方法语句。因为这个抽象方法本身是无法执行的,所以, Weapon
类也无法被实例化。编译器会告诉我们,无法编译 Weapon
类,因为它包含抽象方法。必须把 Weapon
类本身也声明为 abstract
,才能正确编译它:
1 | abstract class Weapon { |
如果一个 class
定义了方法,但没有具体执行代码,这个方法就是抽象方法,抽象方法用 abstract
修饰。
因为无法执行抽象方法,因此这个类也必须申明为抽象类(abstract class)。
使用 abstract
修饰的类就是抽象类。我们无法实例化一个抽象类:
1 | Weapon w = new Weapon(); // 编译错误 |
正确的方法
1 |
|
当我们定义了抽象类 Weapon
,以及具体的 LightAmmo
、 ShotgunAmmo
子类的时候,我们可以通过抽象类 Weapon
类型去引用具体的子类的实例:
1 | Weapon R301 = new LightAmmo(); |
这种尽量引用高层类型,避免引用实际子类型的方式,称之为面向抽象编程。
面向抽象编程的本质就是:
-
上层代码只定义规范;
-
不需要子类就可以实现业务逻辑;
-
具体的业务逻辑由不同的子类实现,调用者并不关心。
2 进一步理解抽象
将复杂的概念进行封装与简化
抽象减少了信息的负载,否则需要全面详细地记录与处理事物的所有细节(熵减)。抽象的目标是简化看待事物的方式,允许忽略一些不重要的东西。
-
编程的时候,并不需要直接操作比特流,这一切都是编译器提供的功能。
- 可以说编译器在编译的时候做了一层抽象。
-
抽象就是隐藏细节,只暴露接口。在使用计算机的usb等接口的时候,我们只需要做连接操作,不需要关心它的具体实现。
- 可以说计算机接口在运行的时候做了一层抽象。
在写代码的时候,我们可以在一开始就定义好接口,然后具体实现的时候再去实现。这样可以提高代码可读性且减少代码量与复杂度。