哈工大 软件构造课程 考点复习总结(第三章)

  1. 数据类型


Primitive types 基本数据类型(8种)

  1. Object types 对象数据类型(reference types 引用数据类型)

Short、int 、long、float、double、boolean、char、byte


如:String、BigInteger


只有值,没有ID(无法与其他值区分),不能赋值为null

immutable


有值,也有ID;

部分mutable,部分immutable


在栈中分配内存,代价低


在堆中分配内存,代价高

  1. 静态类型检查&动态类型检查


静态类型检查


动态类型检查


(静态类型语言 如java)


(动态类型语言 如python)


提高程序的正确性和健壮性

 

关于"类型"的检查,不考虑值(不知道运行时会是什么值)


关于"值"的检查

  1. Mutable & Immutable

     
    Immutable 不可变数据类型


    Immutable 不可变数据类型


    优点


    优点:安全


    优点:最少化拷贝以提高效率获得更好的性能,适合于在多个模块之间共享数据


    缺点


    缺点:频繁修改产生大量临时拷贝,需要垃圾回收·


    缺点:不安全


    其他


    一旦被创建,其值不能改变

    对于引用类型,加final限制不能改变引用


    安全地使用可变类型:局部变量(不涉及共享,且只有一个引用)

    如果有多个引用(别名),不安全

    Defensively copy 防御式拷贝:返回全新的对象

    尽可能用immutable!

  1. Snapshot Diagram 画法:

  2. 基本类型:单独一个常量

    引用类型:圈住!

  3. 重分配:

    不可变类型(用双线椭圆),修改引用

    可变类型:修改值

  4. 引用:

    可变引用:单线箭头

    不可变引用:双线箭头

  1. Specification

  1. 作用

    1. 规约可以隔离"变化",无需通知客户端
    2. 规约可以提高代码效率
    3. 规约扮演"防火墙"角色
    4. 解耦,不需要了解具体实现
  2. 内容:只讲"能做什么",而不讲"怎么实现"
  3. Behavior equivalence 行为等价性

    是否可以相互替换

    1. 站在客户端的视角看行为等价性,不同的行为,对用户来说(根据用户需求)可能等价!
    2. 根据规约判断行为等价,两个方法符合同一个规约,则等价
  4. 规约的结构:
    1. Pre-condition
    2. Post-condition
    3. Exceptional behavior 异常行为,如果违背了前置条件,会发生什么
  5. 规约的强度与替换

    Spec变强:更放松的前置条件(前置条件更弱)+更严格的后置条件(后置条件你更强),

    两条件同时变强或变弱则无法比较。

    若规约强度S2>=S1,则可以用S2替换S1。

  6. deterministic spec & undetermined spec 确定的规约和欠定的规约
    1. 确定的规约:给定一个满足前置条件的输入,其输出唯一、明确
    2. 欠定的规约:同一个输入可以有多个输出(多次执行输出可能不同)
  7. Declarative spec & operational spec 声明式规约和操作式规约
    1. 操作式规约:如 伪代码
    2. 声明式规约:没有内部实现的描述,只有"初-终"状态

    声明式规约更有价值!

    内部实现的细节不在规约里呈现,而放在代码实现体内部注释里呈现。

  8. Diagraming specification

    规约定义一个区域,该区域包含所有可能的实现方式。

    空间中的每个点表示一种方法的实现。

    对于某个具体实现,若满足规约,则落在其区域内。

    更强的规约表达为更小的区域。

  9. Quality of specification 规约质量
    1. 内聚性:spec描述的功能应单一、简单、易理解
    2. 运行结果信息丰富(可能的改变,以及返回值等),不能让客户端产生理解上的歧义
    3. 足够强(如postcondition中充分阐述各种情况)
    4. 适当弱(太强的规约,在很多特殊情况下难以达到)
    5. 在规约里使用抽象类型(在java中,经常使用interface,如Map、List,而不是HashMap、ArrayList),可以给方法的实现体和客户端更大的自由度
    6. 使用前置条件和后置条件?

      客户端不喜欢太强的pre-condition,不满足precondition的输入会导致失败

      So:不限定太强的precondition,而在postcondition中抛出异常:输入不合法,

      fail fast,避免fail大规模扩散

是否使用前置条件取决于:

  1. check(检查参数合法性)的代价
  2. 方法的使用范围:
    1. 如果只在类内部使用(private),则可以不使用precondition,在使用该方法的各个位置进行check
    2. 如果在其他地方使用(public),则必须使用precondition,若client不满足则抛出异常
  1. Pre-condition and post-condition 前置条件和后置条件


Pre-condition 前置条件(requires)


Post-condition 后置条件(effects)


@param


@return @throws


对客户端的约束

在使用方法时必须满足的条件


对开发者的约束

方法结束时必须满足的条件


契约:如果前置条件满足了,后置条件必须满足


除非在后置条件中声明,否则方法内部不应该改变输入参数。

尽量不设计mutating的spec,否则容易引发bugs。

尽量避免使用mutable对象。

避免使用可变的全局变量。

ADT

  1. ADT及其四种操作

    抽象类型:强调"作用于数据上的操作",程序员和client无需关心数据如何具体存储,只需设计/使用操作即可。

    ADT由操作定义,与其内部实现无关。

    可变数据类型:提供了可改变其内部数据值的操作;

    不可变数据类型:其操作不改变内部值,而构造新的对象。(没有mutators

ADT操作分类:

  1. Creators 构造器:

    不利用该类型对象产生一个新的对象

    可能实现为构造函数或静态函数(factory method)

  2. Producers 生产器:

    用已有该类型对象产生新对象

    如string.concat()(连接两个字符串,产生一个新的字符串)

  3. Observers 观察器

    如list.size()返回int(不同于原类型)

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

    通常范围void,如果返回void,则必然意味着它改变了某些对象的内部状态

    也可能范围非空类型(如容器类的put、add方法)

    1. Representation Independence 表示独立性

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

  1. Representation exposure 表示泄漏

如client能直接接触类成员变量。

表示泄漏影响表示不变量,也影响表示独立性:无法在不影响客户端的情况下改变其内部表示。

避免方法:private、final、defensive copy

  1. Invariants 不变量 & Representation Invariant 表示不变量

ADT应保持其不变量在任何时候总是true;

ADT负责其不变量,与client的任何行为无关。

作用:保持程序的"正确性",容易发现错误。

  1. Abstraction Function 抽象函数


表示空间R


抽象空间A


值的实际实现本质


抽象表示(client看到和使用的值)


ADT实现者关注表示空间R


用户关注抽象空间A

R到A的映射

一定是满射:A中元素总有R中具体的实现

未必是单射:A中一个元素在R中可能有多重实现方式

未必是双射:R中表示不符合A中需求(如图中"abbc")

抽象函数AF:R和A之间映射关系的函数

AF:R->A

对于RI :R-> Boolean

RI:某个具体的"表示"是否合法;表示值的一个子集,包含所有合法的表示值;一个条件,描述了什么是"合法"表示值。

  1. Documenting AF 、RI、Safety from Rep Exposure

选择某种特定的表示方式R

进而指定某个子集是"合法"的(RI)

并为该子集中的每个值做出"解释"(AF)

即 如何映射

Safety from Rep Exposure

证明代码并未对外泄露其内部表示

保证不变量为true,不变量:

  1. 通过creators和producers创建
  2. 受mutators和observers保护
  3. 无表示泄漏发生

OOP

  1. Interface 接口

接口的成员变量默认用final关键字修饰,故必须有初值,可用public,default修饰,可用static修饰。

接口的方法只能被public、default、abstract、static、strictfp(严格浮点运算)修饰。

  1. Inheritance、override 继承和重写

Strict inheritance 严格继承:子类只能添加新方法,无法重写超类(父类)中的方法(final限制)。

考虑final修饰类、方法、属性时的不同作用。

Override 方法:具有一致的signature,复用的基本机制。

  1. Polymorphism ,subtyping and overloading 多态,子类型化,重载

三种多态:

  1. Ad hoc polymorphism (特殊多态)

    用于function overloading(功能重载),即重载

  2. Parametric polymorphism (参数化多态)

    泛型

  3. Subtyping (subtype polymorphism / inclusion polymorphism )(子类型多态、包含多态)
  1. Overloading 重载

    1. 重载条件:

      1. 方法名相同
      2. 参数列表不同,即参数类型、个数、类型顺序至少有一项不相同
      3. 返回值类型可以不同
      4. 方法的修饰符可以不同
      5. 可以抛出不同的异常
      6. 可以在类内重载,也可以在子类重载
    2. 重载是一种静态多态,静态类型检查

      (static dispatch 静态分派)并在编译阶段决定具体执行哪个方法(即对方法的调用取决于编译时声明的引用的类型)

      而重写(dynamic dispatch 动态分派)则进行动态类型检查,根据运行时堆中的实例类型选择方法。

  2. Generic 泛型
    1. 通配符 <?> :只有使用泛型的时候出现,不能在定义中出现。
    2. 类型擦除:编译后、运行时类型擦除

      List<Integer> -> List

      注意可能引起重载编译错误。

      运行时不能用 instanceof 检查泛型。

    3. 不能创建泛型数组

      不能用在静态变量

      不能创建对象(不能new)

  3. Subtypes

    超类的子类型,如:ArrayList和LinkedList是List的子类型。

    子类型的规约不能弱化超类型的规约。

    1. 子类型多态:不同类型的对象可以统一处理而无需区分(不加区分地调用同样的方法等),从而隔离变化
    2. LSP(Liskov Substitution Principle) 如果S是T的子类型,那么T的对象可以被S的对象替换。
    3. Type casting 类型转换

      避免向下类型转换。

  4. Dispatch 分派

Static dispatch 静态分派


Dynamic dispatch 动态分派


将调用的名字与实际方法的名字联系起来(可能有多个)


决定具体执行哪一个操作


重载,在编译阶段即可确定执行哪个具体操作


重写,在运行时决定

   

Early/static binding


Lade/dynamic binding


绑定static、private、final方法时发生


重写父类子类的同样方法



  1. equals()

  1. 引用等价性 ==

    比较内存地址ID

    用于比较基本数据类型

  2. 对象等价性 equals()

    验证正确性:reflexive 自反性、symmetric 对称性、transitive 传递性、非空(a.equals(null) return false)

    1. hashCode()

      等价的对象必须有相同的hashCode

      Rule:重写equals时重写hashcode

    1. Equality of Mutable Types 可变对象的等价性


Observational equality 观察等价性


Behavioral equality 行为等价性


在不改变状态的形况下,两个mutable看起来是否一致


调用对象的任何方法都展示出一致的结果


调用observer,producer,creator


调用任何方法,包括mutator


当前情况下,看起来(如成员变量)相同


经过改变后,依然相同(只是别名引用)

对不可变类型,观察等价性和行为等价性完全等价。

对可变类型,往往倾向于实现严格的观察等价性。(但有时观察等价性可能导致bug,甚至破坏RI)

对可变类型,应当实现行为等价性,即只有指向内从空间中同样的objects才相等(即equals比较引用,如==而hashcode把引用映射为一个值)。

所以对可变类型,无需重写equals和hashcode,直接继承object。(比较引用)

若一定要判断两个可变对象是否一致,最好定义一个新的方法。

原文地址:https://www.cnblogs.com/standingby/p/9206630.html

时间: 2024-11-08 18:44:18

哈工大 软件构造课程 考点复习总结(第三章)的相关文章

哈工大 软件构造课程 复习考点总结(第六、七章)

可维护性的常见度量指标 Cyclomatic complexity 圈复杂度 Lines of Code LoC 代码行数 Maintainability Index (MI) 可维护性指数 Depth of Inheritance 继承的层次数 Class Coupling 类之间的耦合度 Unit test coverage 测试代码覆盖率 Coupling 耦合度 and Cohesion 聚合度 Coupling 耦合度: 模块之间的依赖性. Conhesion 聚合度 功能专一性.高聚

麻省理工18年春软件构造课程阅读04“代码评审”

本文内容来自MIT_6.031_sp18: Software Construction课程的Readings部分,采用CC BY-SA 4.0协议. 由于我们学校(哈工大)大二软件构造课程的大部分素材取自此,也是推荐的阅读材料之一,于是打算做一些翻译工作,自己学习的同时也能帮到一些懒得看英文的朋友.另外,该课程的阅读资料中有许多练习题,但是没有标准答案,所给出的答案均为译者所写,有错误的地方还请指出. 译者:李秋豪 审校: V1.0 Thu Mar 8 22:58:41 CST 2018 本次课

HIT软件构造课程3.1总结(data type and type checking)

软件构造的理论基础-ADT 软件构造的技术基础-OOP 1.编程语言中的数据类型 类型和变量  类型是变量的集合,在这些变量集合上我们可以定义运算(类似于代数系统?).栗子:boolean,int,double,String 变量是被命名的位置,这里存储着着一个特定的值.类似于萝卜和坑的关系. java中的类型 java的基本数据类型: int,long,char java的对象数据类型 String,BigInteger java中基本数据类型的字母都是小写的,而对象数据类型词节首字母大写 基

2016.6.13 计算机网络复习要点第三章 数据链路层

**数据链路层使用的信道主要有以下两类: (1)点对点信道:使用一对一的点对点通信方式. (2)广播信道:使用一对多的广播通信方式.广播信道上连接的主机很多,因此必须使用专用的共享信道协议来协调这些主机的数据发送. 3.1使用点对点信道的数据链路层 **链路:就是从一个结点到相邻结点的一段物理线路(有线或无线),而中间没有任何其他的交换结点.链路只是一条路径的组成部分. **数据链路:当需要在一条线路上传送数据时,除了必须有一条物理线路外,还必须有一些必要的通信协议来控制这些数据的传输.若把实现

2016.6.23 计算机网络复习要点第三章之扩展的以太网

**扩展的以太网在网络层看来仍然是一个网络: 1.在物理层把以太网扩展: **以太网上的主机之间的距离不能太远(例如,10BASE-T以太网的两个主机之间的距离不超过200米),否则主机信号经过铜线的传输就会衰减到使CSMA/CD协议无法正常) **现在扩展主机和集线器之间的距离的一种简单的方法就是使用光纤和一对光纤调制解调器: **光纤调制解调器的作用就是进行电信号和光信号的转换,由于光纤带来的时延很小并且带宽很高,因此使用这种方法可以很容易的使主机和几公里以外的集线器相连接: **多级结构的

2016.6.20 计算机网络复习要点第三章之CSMA/CD协议

1.最早的以太网是将许多计算机都连接到一根总线上: (1)总线的特点是:当一台计算机发送数据时,总线上的所有计算机都检测到这个数据,这种就是广播通信方式: (2)为了实现在总线上的一对一通信,可以使每一台计算机的适配器拥有一个与其他适配器都不同的地址,当数据帧中的目的地址与适配器ROM中存放的硬件地址一致时,该适配器才能接收到这个数据帧: (3)人们通常把局域网上的计算机称为“主机”,“工作站”,“站点”或“站” 2.以太网为了通信方便采取的措施: (1)采用较为灵活的无连接的工作方式,即不必先

JS复习:第三章&amp;第四章

第三章 一.把一个值转换成字符串的两种方法: 1.使用每个值都有的toString( )方法.这个方法唯一要做的就是返回相应值的字符串表现.例如: var age = 11 ; var ageAsString = age.toString( ) ;       //字符串”11” var found = true ; var foundAsString = found.toString( ) ;    //字符串”true” 2.在不知道要转换的值是不是null或undefined的情况下,还可

2016.6.21 计算机网络复习要点第三章之使用广播信道的以太网

1.集线器 **双绞线以太网,采用星形拓扑,在星形的中心则增加了集线器. **星形以太网10BASE-T的标准802.3i:“10”表示10Mb/s,BASE表示连接线上的信号是基带信号,T表示双绞线: **集线器的一些特点: ①使用集线器的以太网在逻辑上仍是一个总线网,各站共享逻辑上的总线,使用的还是CSMA/CD协议(即各站的适配器执行CSMA/CD协议): **网站中的各站必须竞争对传输媒体控制,并且在同一时刻至多只允许一个站发送数据: **10BASE-T以太网又称为星型总线或盒中总线:

数据结构复习【第三章】 栈

(1)掌握栈的相关概念.特点和基本操作(入栈.出栈.判栈空.获取栈元素等). 栈:限制只能在表的一端进行插入和删除的线性表. 允许插入和删除的一端,称为栈顶(top). 不允许插入和删除的另一端,称为栈底(bottom). 把一个元素从栈顶放入栈中的操作,称为进栈.入栈或压栈 (push) 从栈顶取出一个元素的操作称为出栈或弹出(pop). 特点:后进先出 (2)掌握顺序栈.链栈.共享栈的实现. 顺序栈: 基本操作: 创建: { base = new T[m]: if (base = = NUL