软件构造第四-八章的小结


前言

本次总结一下软件构造第四章到第八章的内容。


一、第四章 数据类型与类型检验

4.1 先来看看本章的主要内容

在这里插入图片描述
前面一小部分讲解了数据类型的基本知识:
1、数据类型定义了一组值及其可执行的操作。
基本数据类型包括 int、long、boolean、double、char 等。
对象数据类型包括 String、BigInteger 等。
2、静态类型检查与动态类型检查:
静态类型检查在编译时进行,确保变量类型与操作匹配,从而避免运行时错误。
动态类型检查在运行时进行,确保操作合法。

4.2 而重点应该是接下来的可变与不可变数据类型

4.2.1 可变数据类型(Mutable Data Types)

可变数据类型是指其值可以在创建之后被修改的数据类型。这意味着对象在内存中的状态可以被改变。
可变数据类型对象的状态(内容)可以在其生命周期内被改变。而且对可变对象的操作可能更高效,特别是在频繁修改的场景下。但多个引用指向同一对象时,修改对象的状态可能引发不可预期的副作用,导致程序难以调试和维护。

4.2.2 不可变数据类型(Immutable Data Types)

不可变数据类型是指其值在创建之后不能被修改的数据类型。这意味着对象一旦创建,其内容不能被改变。因为不可变数据类型对象的状态不能改变,因此可以安全地在多线程环境下共享。并且会使代码更易于理解,因为对象一旦创建,其状态是确定的。但每次修改都会创建一个新的对象,可能导致性能开销和内存占用增大。

4.2.3 final关键字在Java中的作用
  1. final变量
    定义一个常量,值一旦初始化后便不能改变。

    final int MAX_SIZE = 100;
    
  2. final参数
    方法参数加上final关键字,表示在方法内部不能改变该参数的值。

    public void print(final String message) {
        // message = "New Message";  // 编译错误,不能修改final参数
        System.out.println(message);
    }
    
  3. final方法
    方法加上final关键字,表示该方法不能被子类重写。

    public final void display() {
        System.out.println("This is a final method.");
    }
    
  4. final
    类加上final关键字,表示该类不能被继承。

    public final class Constants {
        // 常量类
    }
    

特别注意的是当一个不可变的基本数据类型加上final修饰后,就不能修改其对应的值了。

4.3 最后一部分是Snapshot(快照)图

在这里插入图片描述

二、第五章 设计规约

5.1 先给出设计规约的定义

设计规约(Design Specification)是描述方法或函数的行为、输入输出条件以及异常处理的文档或注释。良好的设计规约有助于提高代码的可维护性和可靠性。它通常包含以下几个部分:

  1. 方法签名:方法的名称、参数和返回类型。
  2. 前置条件(Preconditions):方法调用前必须满足的条件。
  3. 后置条件(Postconditions):方法调用后必须满足的条件。
  4. 异常(Exceptions):方法可能抛出的异常及其触发条件。

对于一个好的方法,规约是必不可少的,有了规约才知道要怎么设计该方法,别人才知道该怎么使用该方法。一下的一张图就很好的展示了spec的重要性。
在这里插入图片描述

5.2 接下来再来看看规约的设计

在这里插入图片描述越强的规约,意味着implementor的自由度和责任越重,而client的责任越轻!
在这里插入图片描述

三、第六章 抽象数据类型 (ADT)

本章主要学习将数据和操作复合起来,构成ADT,学习ADT的核心特征,以及如何设计“好的”ADT。

6.1 先来看看ADT的分类

可变类型的对象:提供了可改变其内部数据的值的操作;
不变数据类型: 其操作不改变内部值,而是构造新的对象。
ADT内部主要包含如下:
在这里插入图片描述
设计好的ADT,靠“经验法则”,提供一组操作,设计其行为规约 spec

  1. 设计简洁、一致的操作
  2. 要足以支持client对数据所做的所有操作需要,且用操作满足client需要的难度要低
  3. 要么抽象、要么具体,不要混合 — 要么针对抽象设计,要么针对具体应用的设计

在抽象数据类型(ADT)的实现中,抽象函数(AF)、表示不变性(RI)和表示泄露(Representation Exposure)是非常重要的概念。这些概念有助于确保ADT的正确性和安全性。

6.2 再就是ADT中必不可缺的部分了

抽象函数(AF)

抽象函数(AF)描述了具体表示(representation, R)和抽象值(abstract value, A)之间的映射关系。它定义了如何将具体的内部数据结构解释为更高层次的抽象概念。

表示不变性(RI)

表示不变性(RI)定义了具体表示(representation, R)中的所有字段何为有效。这些不变性约束确保对象的状态始终保持一致和有效。

表示泄露(Representation Exposure)

表示泄露(Representation Exposure)是指ADT的内部表示细节被暴露给了外部用户,从而可能导致意外的修改和不一致。避免表示泄露可以提高ADT的安全性和可靠性。

写代码时注意: 在代码中用注释形式精确地记录AF和RI;要精确的记录RI:rep中的所有fields何为有效;要精确记录抽象函数AF:R和A之间映射关系的函数,即如何解释每一个R值,其是满射但未必是单射;表示泄漏的安全声明,给出理由,证明代码并未对外泄露其内部表示;
同时注意:保持不变性和避免表示泄漏,是ADT最
重要的一个Invariant!

四、第七章 面向对象的编程

经历了之前学习的ADT理论,本章就要开始学习ADT的具体实现技术:OOP。
面向对象编程(OOP, Object-Oriented Programming)是一种编程范式,它将程序组织成由数据和行为组成的对象。以下是OOP的核心概念和要素:

1. 对象(Object)

对象是类的实例,表示具体存在的实体。每个对象都有自己的属性和行为。对象是OOP的基本单位。

2. 类(Class)

类是对象的蓝图或模板,定义了对象的属性和行为。一个类可以创建多个对象。(这里提一下接口,接口:确定ADT规约;而类:实现ADT;当然也可以不需要接口直接使用类作为ADT(既有ADT定义也有ADT实现),但实际中更倾向于使用接口来定义变量)

public interface publicCar {
	// 行为
	void drive();
}

class Car implements publicCar {
    // 属性
    String color;
    String model;
    // 行为
    @Override
    void drive() {
        System.out.println("Driving the car...");
    }

class Car {
    // 属性
    String color;
    String model;
    // 行为
    void drive() {
        System.out.println("Driving the car...");
    }
}

3. 封装(Encapsulation)

封装是将对象的属性和方法隐藏在类的内部,只通过公共方法访问。这有助于保护对象的内部状态,防止外部不正当的访问和修改。(使用接口定义就是一个很好的方法,还有private、protect等关键字的使用)

class Person {
    private String name;  // 私有属性
    private int age;
    
    // 公共方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if(age > 0) { // 简单的验证
            this.age = age;
        }
    }
}

4. 继承(Inheritance)

继承是类之间的一种关系,允许一个类(子类)继承另一个类(父类)的属性和行为。子类可以扩展和修改父类的行为。
override:重写的函数:完全同样的signature,而实际执行时调用哪个方法,运行时决定。(但final修饰的方法严格继承,无法被重写)

class Animal {
    void eat() {
        System.out.println("This animal is eating.");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println("The dog is barking.");
    }
}

5. 多态(Polymorphism)

多态允许不同类的对象通过相同的接口调用不同的实现方法。多态性分为编译时多态性(方法重载)和运行时多态性(方法重写)。
多态又分为如下三种:特设多态指的是同一个函数或操作符可以应用于不同的类型,并且每个类型有不同的实现。特设多态通过函数重载(function overloading)来实现。参数化多态指的是编写代码时不指定具体的类型,这样的代码可以与任何类型一起使用。在面向对象编程中,这通常称为泛型编程(generics)。子类型多态指的是同一个名字(如变量或函数)可以表示多个不同类的实例,这些类通过某个公共父类关联起来。也称为包含多态。

class Animal {
    void makeSound() {
        System.out.println("Some sound...");
    }
}

class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Bark");
    }
}

class Cat extends Animal {
    @Override
    void makeSound() {
        System.out.println("Meow");
    }
}

public class TestPolymorphism {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        Animal myCat = new Cat();
        myDog.makeSound();  // 输出:Bark
        myCat.makeSound();  // 输出:Meow
    }
}

6. 抽象(Abstraction)

抽象是将对象的复杂性隐藏起来,只保留必要的特性。这通常通过抽象类和接口实现。
如:某些操作是所有子类型都共有,但彼此有差别,可以在父类型中设计抽象方法,在各子类型中重写(如下一个例子)。如果所有子类型完全相同的操作,放在父类型中实现,子类型中无需重写。再比如有些子类型有而其他子类型无的操作,不要在父类型中定义和实现,而应在特定子类型中实现。

abstract class Animal {
    abstract void makeSound();  // 抽象方法,没有实现
}

class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Bark");
    }
}

class Cat extends Animal {
    @Override
    void makeSound() {
        System.out.println("Meow");
    }
}

总结

面向对象编程通过类和对象将程序组织起来,利用封装、继承、多态和抽象等特性提高代码的可重用性、可维护性和可扩展性。
最后再看看override和overload的区别:
在这里插入图片描述

五、第八章 ADT和OOP中的“等价性”

先来看看本章的关键内容:
在这里插入图片描述
等价关系(Equivalence Relation)是一种定义在集合上的二元关系,具有自反性、对称性和传递性。
站在外部观察者角度:对两个对象调用任何相同的操作,都会得到相同的结果,则认为这两个对象是等价的。反之亦然!
当在自定义ADT时,需要我们重写Object的equals();
在对于等价性书写时,If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result. 等价的对象必须有相同的hashCode;但实际上不相等的对象,也可以映射为同样的hashCode,只是性能会变差。
下面是对于可变数据类型行为等价性的描述:
在这里插入图片描述


总结体会

通过了四到八章的学习,主要的知识内容罗列如下:
在这里插入图片描述
内容很多,知识点很杂,许多细节还得慢慢斟酌体会。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值