第5周作业-继承、多态、抽象类与接口
1.本周学习总结
2.书面作业
1.代码阅读:Child压缩包内源代码
1.1 com.parent包中Child.java文件能否编译通过?哪句会出现错误?试改正该错误。并分析输出结果。
不能通过。问题出在该代码段:
public void getParenti(){
System.out.println(i);
}
这个i的权限是private,对于Child来说并没有权限访问,将它的权限改为protected即可。输出结果应为在Parent中各自定义的i、j的值:
1.2 另外一个包中的OutOfParentPackage.java,能否编译通过?提示什么错误?分析原因。如何更改才能使之正常编译?(写不出来正确答案不要紧,但请一定写出思考过程)
同样不能编译通过。首先,OutOfParentPackage.java文件并不在com.parent包中,Parent根本无法被调用,需要将Parent的权限设置为public;其次,Parent中的j和geti方法均为protected权限,仅限该包内的子类访问,OutOfParentPackage.java文件同样是没有办法访问的,必须将它们的权限改为public。
2.abstract进阶:阅读GuessGame抽象类的设计与使用源代码
2.1 Guess改造前代码很简单,而改造后的代码使用了抽象类、抽象方法看起来很复杂,那这样的改造到底有什么好处呢?
改造前的这串代码在设计出来的时候就已经固定了它只能通过控制台进行输入,相当于被控制台所束缚。改造后将GuessGame类、print方法和nextInt方法定义为抽象类,这样整个程序的执行方式就不再是确定的控制台输入输出,我们具体需要在什么环境下运行它的话只需要创建出一个实例就可以运行,这样做不仅方便在想要的环境下运行,还可以节省代码的冗余。
2.2 如果想将该游戏改造成图形界面,应该进行一些什么操作?
因为游戏的流程是一样的,所以只需将游戏的输入和输出操作改成图形界面里的输入输出就可以了。
2.3 结合该例子,你觉得什么时候应该使用abstract?
在这个例子中,因为这个游戏被设计出来的时候并没有指明它要在什么环境、使用什么方式输入、怎样输出,这时我们并不明白它的具体实现时,我们就应该就把它定义为abstract,由于方法被定义为abstract,所以类也要是abstract类。
2.4 重要:在这个例子中,变化的是什么,不变的是什么?尝试结合abstract、继承等概念进行说明。
这个例子中,整个游戏的游戏流程是不变的:
public void go(){
int number = (int) (Math.random()*10) ;
int guess;
do{
print("输入数字:");
guess = nextInt();
}while(guess != number);
println("猜中了");
}
变化的是游戏要在何种环境运行、如何取得用户的输入、如何显示输出。
变化的部分由于无法确定是,需要将它们定义为abstract,让它们可以根据具体情况来加入具体的实现,到时只需重新定义一个类继承GuessGame的所有对象和方法,在这个新的类里进行抽象方法的具体实现即可。
3.Comparable与Comparator
3.1 描述Comparable接口的用途。为什么某个类实现了Comparable接口就可以直接使用Arrays.sort对其进行排序?
Comparable,顾名思义就是可比较的,根据JDK帮助文件中的描述,此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。
查阅帮助文档中对Arrays.sort方法的描述:
Arrays.sort方法能够使用的前提就是该数组中的所有元素都必须实现了Comparable接口。
3.2 有了Comparable接口为什么还需要Comparator接口呢?
查阅JDK会发现Comparable和Comparator有一个很明显的区别:虽然两个接口的功能描述差不多的,但是所处的包不同。此外,Comparable是将要代码放入自身类其中进行比较,而Comparator是在类外部再写一个外部类来实现比较的接口:
Comparable的实现
private static class Person implements Comparable<Person>{
int age;
String name;
……
boolean equals(Person person) {
if (this.age == person.age && this.name == person.name)
return true;
return false;
}
public int compareTo(Person person) {
return name.compareTo(person.name);
}
}
Comparator的实现(取自之前PTA提交的代码)
public static class MyComparator implements Comparator<String>{
public int compare(String o1, String o2) {
return o1.substring(6, 14).compareTo(o2.substring(6, 14));
}
}
4.面向接口案例分析
阅读Case-StudentDao.zip案例
4.1 画出类关系图,描述每个类与接口的作用。
Student类定义了对象的姓名以及其输出的格式;
StudentDao接口提供了判断是否写入数据、读数据、输出所有学生对象的方法,但未具体实现;
StudenDaoListImpl类是对StudentDao接口中的三个抽象方法的具体实现;
StudentDaoArrayImpl类也是对StudentDao接口中的三个抽象方法的具体实现;
Test主要是实现了界面,创建了三个学生对象,并进行了查找操作。
4.2 StudenDaoListImpl与StudentDaoArrayImpl有何区别?
StudenDaoListImpl与StudentDaoArrayImpl在对StudentDao接口中的三个抽象方法的具体实现并没有出入,只是在数据的存储上有所区别。StudenDaoListImpl创建了一个固定长度的数组,StudentDaoArrayImpl则是创建了一个动态数组,显然是StudentDaoArrayImpl比较节省内存空间。
5.什么是面向接口编程?面向接口编程的好处是什么?
结合题目3与4(Test.java的代码)讨论分析。不要百度原封不动照搬!
在系统分析和架构中,分清层次和依赖关系,每个层次不是直接向其上层提供服务(即不是直接实例化在上层中),而是通过定义一组接口,仅向上层暴露其接口功能,上层对于下层仅仅是接口依赖,而不依赖具体类。
这是网上的一个作者对面向接口编程的理解,说实话这样的理解我现在还理解不来。在我看来,面向接口编程是定义一个或是多个接口,在这些接口中定义一些抽象的方法,在类中使用这些接口里的方法,从而具体实现功能。
面向接口编程可以将接口与实现相分离,从而大大提高程序的灵活性。对于第4题,接口内我们只要提供方法即可,并不需要管他如何去实现,实现的任务交给了类,给我的感觉就像一个过渡句的关联词,起到的只是一个承上启下的作用。
**6.结对编程:面向对象设计(大作业2-非常重要)
内容:使用Java代码完成上周做的面向对象设计大作业,需要有初步界面。实现的功能尽量简单,少而精,只包含必要的功能,不要追求高大全。
写出:类图(尽量精简,不用太多子类)、系统常用功能描述、关键代码与界面
形式: 两人依托码云合作完成。请在这里贴出你们的学号、姓名与任务分工。
201521123107 张翔:主要负责购物车的框架的架构。
201521123084 林正晟:负责购物车个功能的完善。
第一次尝试结对编程这种形式,可以说一开始就犯懵,所以做起来完全就是东一榔头西一棒子,抓不到重点,自己负责构建框架,建着建着连自己都不知道自己在干什么了,好不容易框架搭好了,最后的结果却是看上去好像写了挺多东西,最后却只有一个界面,里面的功能有一部分没有实现,还有一部分没有和界面建立关联,还留下了不少没有解决的问题,bug还是有。可以说这次还是挺失败的。主要原因还是自己编程能力还不够。编写PTA实现比较简单的功能还能应付得过来,当做到这种类似于课设一般的大作业时是真的觉得挺困难的。
商品类:
购物车类:
界面:
注意: 再过几次课要讲Java图形界面编程,到时候要将该系统升级为图形界面。系统的业务逻辑部分应该变化不大,变化大的是输入与输出部分。所以编码的时候,输入(Scanner)与输出(System.out)的代码,请不要将其与某个业务处理函数绑死。
选做加分: 给出两人在码云上同一项目的提交记录截图,额外加分。注:两个人在码云上新建一个项目。**
3.使用码云管理Java代码
本周Commit历史截图
4.PTA实验
实验总结
这次的实验题目不多,而且都是在上机课上做的,感觉上有了老师现场的指点引导,虽然说做起来快了许多,但是觉得自己有很多隐藏的问题没有暴露出来。比如这次PTA的主要内容是对于接口的理解和应用,但是潜意识里有老师的引导,自己就有些懒得去思考,就只要顺着老师的思路走就好了,有一种为了敲代码而敲代码,少了那种在自己理解上敲代码的感觉。
第一题编程题因为在宿舍打过大部分的代码,所以感触比较深,自己一开始认为是自己写一个Comparable接口,后边越写越不对劲,才发现是自己理解错了,其实只需要重写一个compareTo方法就可以了。在提交的时候(怎么总是在提交的时候,汗……)发现样例输出是对的,但是却得到答案错误,起初自己认为是compareTo方法的问题,所以就换了一种写法,改为了三目运算符的形式,结果还错,最后还是在老师的帮助下找到了问题所在——原来是没把文件里的package test;删掉。
第二题用到了Lambda表达式感觉自己并没有理解得十分明白,只是照着老师上机课的讲解,有种生搬硬套的感觉,回头自己会多看看书结合一些代码再加深一下理解。