系列文章目录
哈工大软件构造期末复习(最终章)
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
软件构造还有两天就要考试了,给大家简单总结下知识点,祝大家考个满意的分数。
提示:这里可以添加本文要记录的大概内容:
提示:以下是本篇文章正文内容,下面案例可供参考
一、github指令
Git 是一个开源的分布式版本控制系统
创建本地空仓库
git init
克隆现有存储库,使用clone克隆存储库git clone 可以直接在本地创建相同的仓库。
git clone
将文件添加到缓存区
git add
使用git add命令可以将文件添加到本地仓库的提交缓存,但这个时候还不算添加到了本地仓库,我们还需要使用git commit命令为其添加修改的描述信息。
将暂存区的文件提交到本地仓库
git commit
注意在使用git commit时我们只需要简单描述一下我们做了什么,不要像写注释那样写一大堆。我们需要使用-m命令来简写描述我们的信息。
git commit -m "first commit"
将本地仓库提交到远程仓库
git push
改写提交(–amend:重写上一次的提交信息)
git commit --amend
查看历史提交日志
git log
删除文件
git rm
git创建分支
git branch、git checkout
使用git checkout -b参数来创建一个分支,创建完成分支后会自动切换过去
git checkout -b dev
切换已有分支
git checkout master // 切换到master分支
创建并切换分支
git checkout -b test // 创建并切换到test分支
从指定分支合并到当前分支
git merge test // 将test分支合并到当前分支
查看分支列表
git branch // *代表当前分支
删除本地分支
git branch -d(elete)
删除远程分支
git push origin –d(elete)
然后我们在使用branch来查看当前属于哪个分支,也就是查看HEAD的指向
git branch
如果要查看当前所有分支可以使用
git branch -a
二、代码快照图
代码快照图中最简单的表示就是那些程序中的变量。
只需要用一个箭头指向一个值即可。
稍微复杂一些的是对象表示,需要用一个圈圈住,圆圈里面写上类名。代码快照图中的不可变类型需要用双圈表示,可变类型用单圈
用final修饰的变量,表示不可变的引用。在代码快照图中用双线表示
三、核心知识:ADT
ADT的概念:
ADT(抽象数据类型),强调“作用于数据上的操作”,程序员和用户无需关心数据如何具体存储的,只需设计/使用操作即可。
ADT是由操作定义的,与其内部如何实现无关。
ADT的例子:int 、 String、 List
然后是关于抽象类的操作方法(这个可能考)
主要从例子理解
1.构造器(Creator)。构造器将某一个(某一些)与被构造数据类型不同的数据类型的对象作为参数,构造某个数据类型的具体对象。
例如本次实验中的empty()
2.生产器(Producer)。生产器利用某一类型的数据对象构造出该类型的新的数据对象。(用已有该类型对象产生新对象)
本次实验中没有比较好的例子可以说明,但是注意:
mutator与producer类似,但区别就是mutator会改变fields的内容,而producer不会改变原类。
3.观察器(Observer)。观察器以某一类型的数据作为被观测对象,会返回一个不同数据类型的值。
例如本次实验中的sources(L target)、targets(L source)
4.变值器(Mutator)。变值器改变某个对象的属性。只有可变才有变值器。
例如本次实验中的add(L vertex)、set(L source, L target, int weight)、remove(L vertex)。
测试ADT的思路:
测试creators, producers, and mutators:调用observers来观察这些 operations的结果是否满足spec;
测试observers:调用creators, producers, and mutators等方法产生或 改变对象,来看结果是否正确。
举例:
四、AF、RI、表示泄露
首先注意一个概念:
Representation Independence 表示独立性 (不是Representation invariant)
表示独立性:用户不必考虑ADT内部如何实现,ADT内部的改变不影响外部使用
然后是我们默认的RI:
RI:Representation invariant(表示不变量)
注明抽象值的合法区域。在该类中你定义了哪些变量(即域(field),非临时变量),这些变量的取值有哪些特殊要求和边界条件。
Invariants:– 不可变性是一个至关重要的不变量:一旦创建,不可变对象应该在其整个生命周期内始终表示相同的值。
抽象函数AF:
R和A之间映射关系的函数,即如何去解 释R中的每一个值为A中的每一个值。 满射、非单射、未必双射。
R ==>A 一定是满射,但不一定是单射.
单射:指将不同的变量映射到不同的值的函数。
满射:指陪域等于值域的函数。即:对陪域中任意元素,都存在至少一个定义域中的元素与之对应。
双射(也称一一对应):既是单射又是满射的函数。
举例:
Rep Exposure:表示泄露:
给出代码内部表示没有向外部泄露的理由
五、设计规约
规约的内容
输入/输出的数据类型。
功能和正确性期望。
性能要求。
规约的结构
前置条件:对客户端的约束,在使用方法时必须满足的条件。
后置条件:对开发者的约束,方法结束时必须满足的条件。
契约:如果前置条件满足了,后置条件必须满足;前置条件不满足,则方法可做任何事情,也就是“你违约在先,我自然不需要遵守承诺”。
我们判断行为等价性,也就是判断这两个函数是否可以相互替换。我们可以看到,这两个函数在行为上是不同的,但是对于客户端来说,这两个函数都符合同一个规约。
Java中方法参数写在 @param 后面,返回值写在 @return 后面,可能抛出的异常写在 @throws 后面。其中, @param 后面的是前置条件, @return 和 @throws 后面的是后置条件
规约只关注方法的输入输出,不关注方法内部的局部变量和私有域
除非在后置条件里声明过,否则方法内部不应该改变输入参数。
程序员之间应达成的默契:
除非规约必须如此,否则不应修改输入参数。
mutable对象会使规约复杂化。
规约的确定性
规约的确定性指描述的输出是否确定。
规约的陈述性
规约的陈述性指仅仅描述了输出,还是描述了计算过程(不应该这样做,这样相当于暴露了内部实现过程)。
规约的强度
规约的强度用于判断哪种规约更好。
规约的强度S2>=S1就可以用S2替换S1,规约的强度指更放松的前置条件和更严格的后置条件。也就是更少的要求,更多的承诺。
图形化规约
用椭圆内的区域表示所有对规约的实现,椭圆内的每个点表示一种实现。椭圆的面积表示规约的实现有多少种。程序员可以在规约范围内自由选择实现方式,客户端也无需了解具体使用了哪个实现。
更强的规约表达为更小的区域。
更强的后置条件–>实现的自由度更低–>在图中的面积更小
更弱的前置条件–>要处理更多的可能输入–>实现的自由度更低–>面积更小
欠确定性:规范允许同一输入有多个有效输出。
六、override 和 overload
@Override是Java的元数据,自动加上去的一个标志,告诉你说下面这个方法是从父类/接口 继承过来的,需要你重写一次,这样就可以方便你阅读,也不怕会忘记
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 形参不能改变,返回值按照下面的规则修改:
基本类型:子类返回值类型必须等于父类返回值类型。
引用类型:子类返回值类型小于或等于父类返回值类型。
重写的好处在于子类可以根据需要,定义特定于自己的行为。 也就是说子类能够根据需要实现父类的方法。
重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。
@Override是伪代码,表示重写(当然不写@Override也可以)。不过写上有如下好处:
1、可以当注释用,方便阅读;
2、编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错。
声明为 final 的方法不能被重写。
声明为 static 的方法不能被重写,但是能够被再次声明。
子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法。
子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法。
@Overload
重载(overloading) 是在一个类里面,方法名字相同,而参数不同。返回类型可以相同也可以不同。
每个重载的方法(或者构造函数)都必须有一个独一无二的参数类型列表。
最常用的地方就是构造器的重载。
重载的方法在使用时通过参数进行区别
被重载的方法必须改变参数列表(参数个数或类型不一样);
被重载的方法可以改变返回类型;
总结
提示:这里对文章进行总结:
上面就是几个期末非常重要的知识点,希望大家都能掌握,考出理想的成绩!