前言:本文将介绍数据类型从无到有的一步步不断进行抽象的过程以及数据类型发展所带来的好处。
一、发展历史
目前,数据类型的发展经历了四个阶段:无数据类型、基本数据类型、自定义数据类型、抽象数据类型。
第一阶段:无数据类型
数据,如字符、数值等,都是0和1组成的串。当然操作(或者说运算)也不例外。这样的语言称为机器语言。当你的程序想要使用数据字符’a’时,你首先需要确定该程序使用何种编码,假设使用ISO-8859-1,字符’a’的码值是97,因此在程序中你要这样描述一个字符01100001
;然而,如何在程序中描述一个数字呢?为了方便计算,个人认为应该是使用补码来描述一个数字,因此数字1在程序中是这样描述的00000001
。在操作眼中,根本不知道你的0、1串是字符还是数值,因此有可能出现对字符进行乘除操作的情况。
第二阶段:基本数据类型
数据类型: 一组值和一组对这些值的操作的集合。常见的编程语言中,如c、java,都会存在基本的数据类型,如下图所示
从此,数据不再是0和1组成的串,数据有了不同的类型。我们在程序中想要使用字符’a’和数字1,只需要如此char ch = 'a'; int num = 1;
程序开发人员不需要在关心数据在机器内部的细节。另外,编译器可以帮助我们检查对数据操作的合法性。
对于基本数据类型,一组值和一组对这些值的操作的集合
值的集合{…,-1,0,1},操作的结合{+、-、*,/,%,…}
第三阶段:用户自定义数据类型
有了基本数据类型之后,我们在处理字符和数的时候就方便多了。按理说有了基本数据类型,就可编写任何程序来处理不同的数据,但是对于复杂的数据对象,例如:书、学生等,处理就比较麻烦。以“学生”为例,它包含的数据项为{姓名,年龄}
#include <stdio.h>
#include <stdlib.h>
void printStuInfo(char* name, int age){
printf("name = %s, age = %d\n",name, age);
}
void main(){
// 处理两个学生bob和mary的信息
char* bobName = "Bob";
int bobAge = 18;
char* maryName = "Mary";
int maryAge = 17;
printStuInfo(bobName, bobAge);
printStuInfo(maryName, maryAge);
}
执行结果如下:
对于复杂的数据对象,即包含了很多数据项的数据对象,由于现在只有基本数据类型,我们无法将该数据对象作为一个整体或者某种数据类型的对象来处理,因此,在处理时,不得不花费时间在数据的表示细节上。可读性差,作为函数的参数处理时也容易出错。
因此,就有了自定义数据类型。例如:C语言中的“结构体”。程序开发人员不用再关心数据的表示细节,换句话说,可以把复杂的数据对象作为某个数据类型的对象(或者作为一个整体)来处理。
使用自定义数据类型来重新实现“处理两个学生bob和mary的信息”。
#include <stdio.h>
#include <stdlib.h>
struct student{
char* name;
int age;
};
void init(struct student* s, char* name, int age){
s->name=name;
s->age=age;
}
void printStu(struct student* s){
printf("name=%s, age=%d\n", s->name, s->age);
}
void main(){
struct student bob, mary;
init(&bob, "Bob", 20);
init(&mary, "Mary", 21);
printStu(&bob);
printStu(&mary);
}
执行结果如下:
对于用户自定义数据类型,一组值和一组对这些值的操作的集合
值的集合{【“Bob”,18】,【“mary,17”】},操作的集合{init,printStu}
第四阶段:抽象数据类型
在基于功能抽象的模块化设计方法中,模块间的连接是通过数据进行的,数据中一个模块传送到另一个模块。每一个模块在其上施加一定的操作,完成一定的功能。C语言等的用户自定义类型机制使得这些连接数据可以作为某种类型的对象直接处理。然而,用户自定义类型的表示细节是对外公开的,没有任何保护措施。我可以上面的main函数中添加语句bob.age=-1
。在多人合作开发的大型软件系统中,程序开发人员可以随意修改对象的数据,而其他模块却一无所知,由此可能带来巨大的危害。20世纪60年代的“软件危机”就是因为软件开发中不能有效的控制数据的表示细节引起的。为了解决这一问题,我们需要使类型的内部表示细节对外界不可见。
于是,抽象数据类型诞生了。相对于用户自定义数据类型,数据的内部表示细节对外部不可见,访问数据的唯一方式就是数据类型提供的操作(即方法)。这一机制称为封装
二、总结
对上文内容的总结,主要介绍一下优缺点等。
发展历史 | 特点 | 代表语言 |
---|---|---|
无数据类型 | 数据没有类型,使用0、1串表示 | 机器语言 |
基本数据类型 | 不用考虑数据的在机器内部的表示 | Fortran、Algol |
用户自定义数据类型 | 不用考虑数据的表示细节 | C语言 |
抽象数据类型 | 隐藏了数据的表示细节 | Java |