【ADT的基本概念】程序员
- 抽象数据类型(Abstract Data Type,ADT)是是指一个数学模型以及定义在该模型上的一组操做;即包括数据数据元素,数据关系以及相关的操做。
- ADT具备如下几个能表达抽象思想的词:
- 抽象化:用更简单、更高级的思想省略或隐藏低级细节。
- 模块化: 将系统划分为组件或模块,每一个组件能够设计,实施,测试,推理和重用,与系统其他部分分开使用。
- 封装:围绕模块构建墙,以便模块负责自身的内部行为,而且系统其余部分的错误不会损坏其完整性。
- 信息隐藏: 从系统其他部分隐藏模块实现的细节,以便稍后能够更改这些细节,而无需更改系统的其余部分。
- 关注点分离: 一个功能只是单个模块的责任,而不跨越多个模块。
- 与传统类型定义的差异:
- 传统的类型定义:关注数据的具体表示。
- 抽象类型:强调“做用于数据上的操做”,程序员和client无需关心数据如何具体存储的,只需设计/使用操做便可。
-
ADT是由操做定义的,与其内部如何实现无关!编程
【ADT的四种类型】编程语言
- 前置定义:mutable and immutable types
- 可变类型的对象:提供了可改变其内部数据的值的操做。Date
- 不变数据类型: 其操做不改变内部值,而是构造新的对象。String
-
- Creators(构造器):
- 建立某个类型的新对象,⼀个建立者可能会接受⼀个对象做为参数,可是这个对象的类型不能是它建立对象对应的类型。可能实现为构造函数或静态函数。(一般称为工厂方法)
- t* -> T
- 栗子:Integer.valueOf( )
- Producers(生产器):
- 经过接受同类型的对象建立新的对象。
- T+ , t* -> T
- 栗子:String.concat( )
- Observers(观察器):
- 获取抽象类型的对象而后返回一个不一样类型的对象/值。
- T+ , t* -> t
- 栗子:List.size( ) ;
- Mutators(变值器):
- 改变对象属性的方法 ,
- 变值器一般返回void,若为void,则必然意味着它改变了对象的某些内部状态;固然,也可能返回非空类型
- T+ , t* -> t || T || void
- 栗子:List.add( )
- 解释:T是ADT自己;t是其余类型;+ 表示这个类型可能出现一次或屡次;* 表示可能出现0次或屡次。
【设计一个好的ADT】模块化
设计好的ADT,靠“经验法则”,提供一组操做,设计其行为规约 spec函数
- 原则 1:设计简洁、一致的操做。
- 最好有一些简单的操做,它们能够以强大的方式组合,而不是不少复杂的操做。
- 每一个操做应该有明确的目的,而且应该有一致的行为而不是一连串的特殊状况。
- 原则 2:要足以支持用户对数据所作的全部操做须要,且用操做知足用户须要的难度要低。
- 提供get()操做以得到list内部数据
- 提供size()操做获取list的长度
- 原则 3:要么抽象、要么具体,不要混合 —— 要么针对抽象设计,要么针对具体应用的设计。
【测试ADT】性能
- 测试creators, producers, and mutators:调用observers来观察这些 operations的结果是否知足spec;
- 测试observers: 调用creators, producers, and mutators等方法产生或改变对象,来看结果是否正确。
## OOP的基本概念
【对象】测试
- 对象是类的一个实例,有状态和行为。
- 例如,一条狗是一个对象,它的状态有:颜色、名字、品种;行为有:摇尾巴、叫、吃等。
- 概念:一个对象是一堆状态和行为的集合。
- 状态是包含在对象中的数据,在Java中,它们是对象的fields。
- 行为是对象支持的操做,在Java中,它们称为methods。
【类】设计
- 类是一个模板,它描述一类对象的行为和状态。
- 每一个对象都有一个类
- 类定义了属性类型(type)和行为实现(implementation)
- 简单地说,类的方法是它的应用程序编程接口(API)。
- 类成员变量(class variable)又叫静态变量;类方法(class method)又叫静态方法:
- 实例变量(instance variable)和实例方法(instance method)是不用static形容的实例和方法;
- 两者有如下的区别:
- 类方法是属于整个类,而不属于某个对象。
- 类方法只能访问类成员变量(方法),不能访问实例变量(方法),而实例方法能够访问类成员变量(方法)和实例变量(方法)。
- 类方法的调用能够经过类名.类方法和对象.类方法,而实例方法只能经过对象.实例方法访问。
- 类方法不能被覆盖,实例方法能够被覆盖。
- 当类的字节码文件被加载到内存时,类的实例方法不会被分配入口地址 当该类建立对象后,类中的实例方法才分配入口地址, 从而实例方法能够被类建立的任何对象调用执行。
- 类方法在该类被加载到内存时,就分配了相应的入口地址。 从而类方法不只能够被类建立的任何对象调用执行,也能够直接经过类名调用。 类方法的入口地址直到程序退出时才被取消。
- 注意:
- 当咱们建立第一个对象时,类中的实例方法就分配了入口地址,当再建立对象时,再也不分配入口地址。
- 也就是说,方法的入口地址被全部的对象共享,当全部的对象都不存在时,方法的入口地址才被取消。
- 总结:
- 类变量和类方法与类相关联,而且每一个类都会出现一次。 使用它们不须要建立对象。
- 实例方法和变量会在每一个类的实例中出现一次。
【接口】指针
- 概念:接口在JAVA编程语言中是一个抽象类型,用于设计和表达ADT的语言机制,其是抽象方法的集合,接口一般以interface来声明。
- 一个类经过继承接口的方式,从而来继承接口的抽象方法。
- 接口并非类,编写接口的方式和类很类似,可是它们属于不一样的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
- 一个接口能够扩展其余接口,一个类能够实现多个接口;一个接口也能够有多重实现
- 除非实现接口的类是抽象类,不然该类要定义接口中的全部方法。
- 接口没法被实例化,可是能够被实现。一个实现接口的类,必须实现接口内所描述的全部方法,不然就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们能够成为一个空指针,或是被绑定在一个以此接口实现的对象。
总结:接口的好处code
-
Safe from bugs
ADT是由其操做定义的,接口就是这样作的。
当客户端使用接口类型时,静态检查确保他们只使用由接口定义的方法。
若是实现类公开其余方法,或者更糟糕的是,具备可见的表示,客户端不会意外地看到或依赖它们。
当咱们有一个数据类型的多个实现时,接口提供方法签名的静态检查。
-
Easy to understand
客户和维护人员确切知道在哪里查找ADT的规约。
因为接口不包含实例字段或实例方法的实现,所以更容易将实现的细节保留在规范以外。
-
Ready for change
经过添加实现接口的类,咱们能够轻松地添加新类型的实现。
若是咱们避免使用静态工厂方法的构造函数,客户端将只能看到该接口。
这意味着咱们能够切换客户端正在使用的实现类,而无需更改其代码。
【抽象类】
- 抽象类除了不能实例化对象以外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类同样。
- 因为抽象类不能实例化对象,因此抽象类必须被继承,才能被使用。
- 父类包含了子类集合的常见的方法,可是因为父类自己是抽象的,因此不能使用这些方法。
- 在Java中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却能够实现多个接口。
- 若是一个类包含抽象方法,那么该类必须是抽象类。
- 任何子类必须重写父类的抽象方法,或者声明自身为抽象类。
- 构造方法,类方法(用static修饰的方法)不能声明为抽象方法。
## OOP的不一样特征
【封装】
- 封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。
- 设计良好的代码隐藏了全部的实现细节
- 干净地将API与实施分开
- 模块只能经过API进行通讯
- 对彼此的内在运做不了解
- 信息封装的好处
- 将构成系统的类分开,减小耦合
- 加快系统开发速度
- 减轻了维护的负担
- 启用有效的性能调整
- 增长软件复用
- 信息隐藏接口
- 使用接口类型声明变量
- 客户端仅使用接口中定义的方法
- 客户端代码没法直接访问属性
【继承与重写】
- 继承概念:继承就是子类继承父类的特征和行为,使得子类对象(实例)具备父类的实例域和方法,或子类从父类继承方法,使得子类具备父类相同的行为。
- 重写概念:重写是子类对父类的容许访问的方法的实现过程进行从新编写, 返回值和形参都不能改变。即外壳不变,核心重写!
- 重写的好处在于子类能够根据须要,定义特定于本身的行为。 也就是说子类可以根据须要实现父类的方法。
- 实际执行时调用那种方法,在运行时决定
- 重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。
- 子类只能添加新方法,没法重写超类中的方法。
- 当子类包含一个覆盖超类方法的方法时,它也可使用关键字
super
调用超类方法。