要解决的问题:
无论是传统世界,还是编程世界,我们都在干一件事情,
那就是通过使用一种更为通用的方式( 就是抽象和隔离 ),让复杂的“世界”变得简单一些。
例如:怎么用一把螺丝刀拧开所有螺丝?
依据 :程序 = 算法 + 数据
理想情况下,算法应是和数据结构以及类型无关的,各种特殊的数据类型理应做好自己分内的工作,算法只关心一个标准的实现。
编程语言发展到今天,出现了好多不同的代码编写方式,但不同的方式解决的都是同一个问题,那就是如何写出更为通用、更具可重用性的代码或模块。
例如:怎么用一段加法程序,处理所有数据的加法计算
要做到抽象,第一个要拿出来讲的就是抽象类型——泛型编程。
类型
类型系统 :用于定义如何将编程语言中的数值和表达式归类为许多不同的类型,以及如何操作这些类型,还有这些类型如何互相作用。
编译器可能使用静态类型 以最优化所需的存储区,选取运算时的最佳算法
如果一个变量用动态类型,就不知道要占用多大存储空间,也无法知道用什么算法最优
任何语言都有类型系统,一般来说,编程语言会有两种类型,
- 一种是内建类型,如 int、float 和 char 等,
- 一种是抽象类型,如 struct、class 和 function 等。
类型的本质
类型是对内存的一种抽象
。不同的类型,会有不同的内存布局和内存分配的策略。- 不同的类型,有不同的操作。所以,对于特定的类型,也有特定的一组操作。
泛型
开头说过 我们在找更为通用的方式,就是 泛型 :使用一段代码,处理所有的类型。
- 类型带来的问题
作用于不同类型的代码,虽然长得非常相似,但是由于类型的问题需要根据不同版本写出不同的算法,如果要做到泛型,就需要涉及比较底层的玩法。
泛型的方案
对此,分出了两类语言,
一类是静态类型语言,如 C、C++、Java,
一种是动态类型语言,如 Python、PHP、JavaScript 等。
无论哪种程序语言,都避免不了一个特定的类型系统。哪怕是可随意改变变量类型的动态类型的语言,我们在读代码的过程中也需要脑补某个变量在运行时的类型。
不同的语言在设计上都会做相应的取舍,比如:
C 语言偏向于让程序员可以控制更多的底层细节,
而 Java 和 Python 则让程序员更多地关注业务功能的实现。
而 C++ 则是两者都想要,导致语言在设计上非常复杂。
泛型编程
泛型的本质
-
要做到泛型,我们需要做下面的事情:
- 标准化掉类型的内存分配、释放和访问。
- 标准化掉类型的操作。比如:比较操作,I/O 操作,复制操作……
- 标准化掉类型上特有的操作。
- 标准化掉数据容器的操作。比如:查找算法、过滤算法、聚合算法……
-
其本质就是
屏蔽掉数据和操作数据的细节,让算法更为通用,
让编程者更多地关注算法的结构,而不是在算法中处理不同的数据类型。
方案
- 类、模板、虚函数和运行时识别 等等
一个良好的泛型编程需要解决如下几个泛型编程的问题:
- 算法的泛型;
- 类型的泛型;
- 数据结构(数据容器)的泛型。
而对于泛型的抽象,我们需要回答的问题是,如果我们的数据类型符合通用算法,那么对数据类型的最小需求又是什么呢?
C++ 是如何有效解决程序泛型问题
- 它通过类的方式来解决。
可以让一个用户自定义的数据类型和内建的那些数据类型就很一致了 - 通过模板达到类型和算法的妥协。
模板很好地取代了 C 时代宏定义带来的问题 - 通过虚函数和运行时类型识别。
就可以写出基于抽象接口的泛型。