抽象数据类型(ADT)

开始学习面向对象编程时,总是会被直接告诉说,面向对象编程对重要的就是ADT和OOP,可能学完了都不知道到底是啥,其实这东西就是个概念,我们去接受知识的时候,就抱着什么是?啥特点?怎么实现?这三点学习我们要接受的新知识就好,不要被大把的概念吓到。

这里就说一下我认为的ADT(Abstract Data Type)

1.什么是ADT?

在说ADT之前我们基本都是从面向过程过来的,想想当你去写一个c语言程序时,你对过程的把握主要依赖于你对数据的具体表示的把握,然后基于此去实现过程。ADT之所以不同就在于此,这里我们将过程分化成一个一个的操作,而先不去关心数据的具体实现,说白了ADT就是一组操作,由操作(与规约specs)定义,与其内部实现无关比如我们说List,我们只需要知道可以add,可以get等操作就够了。具体的实现不是ADT需要考虑的。

1.1具体的操作分类

刚说完ADT是一组操作,那操作具体就分为四种,分别如下:

        (1)Creators(构造器):从无到有

        (2)Producers(产生器):从有到新

        (3)Observers(观察器):例如get()

        (4)Mutators(变值器):改变对象属性的方法set()

这张图可以更佳清楚的看出四种操作的特点。 

这里需要注意的一点是不可变数据类型没有Mutators,很容易理解不可变嘛,就不能改变其属性,改变了就只能重写创建一个了。

2.ADT的特点

这里特点主要有表示独立性(Representation Independence),不变性(Invariants),表示不变性和抽象函数(Rep Invariant and Abstraction Function(RI and AF))。

2.1表示独立性(Representation Independence)

        定义:client使用ADT是无需考虑其内部如何实现,ADT内部表示的变化不应该影响外部spec和客户端。

表示独立性是很重要的概念,后面的可扩展性等性质都基于表示独立性,这里说白了就是我ADT的定义的操作及其spec完全足够你使用我ADT了,其他的你不用管,我怎么表示和你怎么用是分开的,我修改我的表示,对你的使用也没影响,你要的功能我肯定能通过不同的表示给你。你客户端也得守规矩,不用管我怎么实现的,你就使用我给你ADT的操作。

2.2不变量(Invariants

啥叫不变量呢,这没有明确定义,但是字面意思就是,我的某个表示,在他被初始化之后,我是不希望它变化的,就像一个Person类我们假设每个人的性别在生理上是不可变的,那么我们在给Person对象指定性别之后,无论这个Person怎么去使用,他的性别属性就是不变的,这就是一个不变量。

这里是由ADT来保护不变量的,要检查不变量是否改变,要是改变了就说明有错误了,那Person对象的性别改变了,那还得了,每个Person都得自己保护自己的性别啊,别人怎么蹂躏你原则不能改变。

这里不变的数据类型很容易保证其不变性,但是如果是可变数据类型呢,那就涉及一个概念:表示泄露

2.2.1 表示泄露

表示泄露就是把我内部的表示透露给了客户端,这不仅影响不变量还影响表示独立性,每个ADT都要避免表示泄露,不能让外部得到自己的具体表示。

方法主要有peivate final代替public,或者直接使用不可变数据类型,或者使用防御式复制,对可变类型返回副本,再不济只能告诉客户端不要去修改,当然这不是最好的,因为客户永远最奇怪

2.3RI和AF

其实我对这俩定义觉得有些抽象,先大致理解一下,这里其实也是遵循一个独立的概念,也就是说,客户看到和使用的表示存在于抽象空间(A),程序员看到的表示存在于表示空间(R),你客户是上帝,客户能看到和使用的值你程序员就必须表示出来,因此R对A是满射的,但未必是单射和双射,只要能满足用户就行。

2.3.1AF

其中AF就表示这种R和A之间的映射关系,即如何将R中的每一个值解释为A中的每一个值,前面也解释了,这种映射是满射,未必单射和双射。

2.3.2RI

RI就是说某个具体的表示是否合法

前面不是说R空间到A空间不必是单射和双射么,我给定一个表示,那我R空间就很大呀,其中有很多具体表示可能存在映射关系,而有些表示不符合要求就是不合法的,RI就定义了那些表示是合法的,也就是说R空间中那些值是合法的。

这里需要注意要及时检查你的RI是否是对的,因此需要在每个可能改变rep的方法内都要检查。

3.怎么设计ADT

(1)设计简洁,一致的操作

(2)要足以支持client对数据所作的所有操作的需要,且用操作满足client需要的难度要低

(3)要么抽象,要么具体,不要混合。

4.总结

这里我其实还是有一些疑问的,要是单纯说ADT我是理解的,就是定义了一些操作的集合,其中对每个操作都有明确的spec,来确保用户能够正确使用这个ADT,但是涉及到ADT的特性我就产生了疑问,这写明明都是实现过程中的需要注意的,比如RI,AF,不变量等概念都是在实现时程序员去思考的,然后以注释的形式写进去的,不会被client看到,为什么说是ADT的特性呢?这里我认为可以这么理解,正是这些特征才能保证ADT是真正作为一个中介在客户端和程序员之间作为桥梁,客户通过文档了解ADT的功能去使用它,程序员通过ADT的特征去用具体的实现去表示,同时遵循这些特征才能保证ADT的对于用于用户来说是完全独立于实现的。因此这些特性是必要的,我的理解就是这样,希望有人可以与我分享自己的看法。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值