c语言 如何创建adt_编程那些事儿:面向对象编程基石之数据抽象(ADT)

871b47950488811198ad7a2cd0238b2b.png

数据抽象

本文接上一篇《编程那些事儿:为什么说抽象是面向对象编程的根基【1】?》,

在了解了面向对象编程抽象的过程抽象后,下面我们继续聊一下数据抽象

数据抽象可以说面向对象编程最重要的基石。而数据抽象的结果就是数据类型(或简单的类型),它一般由以下三个部分定义:

  • 一组值(或数据对象)。
  • 一组操作,可应用于该集合中的所有值。
  • 一种数据表示,它决定如何存储值。

通常编程语言会提供一些预定义的数据类型,称为内置数据类型

他们也允许程序开发人员定义自己的数据类型,这被称为用户定义的数据类型

由原子值和不可分割值组成的数据类型称为原始数据类型,它的定义不需要任何其他数据类型的帮助。例如,Java具有内置的基元数据类型,比如int, float, boolean, char等。

按照数据抽象的组成结构,Java中定义int基元数据类型的三个组成部分如下:

  • 值:int数据类型由-2147483648和2147483647之间的所有整数组成。
  • 操作:为int数据类型定义了加法、减法、乘法、除法、比较等操作。
  • 数据表示:int数据类型的值以2的补码形式在32位内存中表示。

int数据类型的所有三个组件都是由Java语言预定义的。开发人员不能扩展或重新定义int数据类型的定义。

我们具体拿int 类型看一下它的抽象内容,比如:

int i;

该语句说 i 是一个名称(技术上称为标识符),可以与定义int数据类型值的一组值中的一个值关联。

例如,可以使用下面的赋值语句将整数100与名称i关联:

i = 100;

在此阶段,您可能会问,“与i关联的值100存储在内存中何处?” 根据int数据类型的定义,i将占用32位内存。

但是,您不知道,不能知道,也不需要知道在内存中为i分配32位空间的位置,这样做也是一种抽象。在像Java这种高级语言中,像这样的抽象的例子比比皆是。

eb5e67c2abb19632d13d7756e784a0ff.png

面向对象编程语言

在本例中,关于int数据类型的数据值的数据表示内存形式对数据类型的用户(程序员)来说是隐藏的。

换句话说,程序员会忽略i的内存位置,而专注于它的值和可以在其上执行的操作。

程序员并不关心i的内存是分配在寄存器、RAM还是硬盘中。

面向对象的编程语言(如Java)允许我们使用抽象机制创建新的数据类型称为数据抽象。

以此创建的新的数据类型被称为抽象数据类型(ADT)

ADT的数据对象可能包括原始数据类型和其他ADT的组合,ADT定义了一组可以应用于其所有数据对象的操作,但其数据表示却总是隐藏在ADT中。

对于ADT的用户来说,他们只知道如何操作该数据,只能使用这些操作来处理它的数据元素。

使用数据抽象的好处是,它的数据表示可以在不影响使用ADT的任何代码的情况下进行更改。

总结一下,数据抽象允许程序员创建一个称为抽象数据类型的新数据类型,其中数据对象的存储表示形式对数据类型的用户是隐藏的。

换句话说,ADT仅仅是根据可以应用于其类型的数据对象的操作来定义的,而不需要知道数据的内部表示形式。

这种数据类型之所以称为抽象,是因为ADT的用户从来没有看到过数据值的表示。

用户以抽象的方式查看ADT的数据对象,方法是在不了解数据对象表示细节的情况下对它们应用操作。

当然,ADT并不意味着数据类型构成中没有数据表示。数据表示在ADT中是肯定存在的,只是对用户隐藏了数据表示而已。

Java有一些数据结构构造,比如类、接口、注释和枚举,这些构造都允许我们用它来定义新的ADT。

注意在我们使用一个类来定义一个新的ADT时,需要小心地隐藏数据表示,这样我们的新数据类型就真的是抽象的了。

如果我们Java类中的没有隐藏数据表示,该类将创建一个新的数据类型,而不再是ADT。

Java中的类提供了一些特性,我们可以使用这些特性公开或隐藏数据表示。

cefdbedce7335706a3235031a3e13c89.png

数据抽象编码

在Java语言中,我们拿类Class这个抽象数据类型来看它的三个组成部分:

其中数据类型是Object,其操作方法是methods,数据类型的表示就是我们的定义的私有字段。

我们可以通过Class中定义的方法来实现对字段(数据表示)的操作。

在Java语言中,有一个纯种的ADT,那就是接口(interface),它只提供了数据的操作部分,而没有具体的实现。

而它的数据值部分和数据表示部分都是实现它的具体类提供的。

public class Person{private String name;private String gender;public Person(String name, String gender){this.name = name;this.gender = gender;}public String getName(){return name;}public void setName(String name){this.name = name;}public String getGender(){return gender;}}

比如:使用Java语言语法定义Person类。通过定义一个名为Person的类,我们就创建了一个新的ADT。

我们定义内部属性name和gender就是其内部数据表示,它们使用String数据类型(String是Java类库提供的内置ADT)。

我们可以注意到,Person类的定义在name和gender声明中使用private关键字来隐藏它。所以Person类的用户不能访问name和gender数据元素。

它提供了四个操作:一个构造函数和三个方法(getName、setName和getGender)。

构造函数操作用于初始化新构造的Person类型的数据对象。getName和setName操作分别用于访问和修改name数据元素。

getGender操作用于访问性别数据元素的值。

Person类的用户只能使用这四个操作来处理Person类型的数据对象。

Person类型的用户不知道用于存储name和gender数据元素的数据存储类型。

我上面使用了三个词,“数据类型”、“类”和“接口”,其实在某种意义上说,它们可以互换使用,因为它们在数据类型上下文中的意思是相同的。

它让Person类型的开发人员可以自由地更改name和gender数据元素的数据表示形式,而不会影响任何Person类型的用户。

假设其中一个Person类型的用户有以下代码片段:

Person john = new Person("Si Li
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值