第5周-继承、多态、抽象类与接口

1. 本周学习总结

1.1 使用思维导图总结有关多态与接口的知识点。

1.2 可选:使用常规方法总结其他上课内容。

我的总结:

  • 泛型数组列表:ArrayList(类似普通数组,属于对象包装器)——当数组的全部空间被用尽时,数组列表将自动地创建一个更大的数组,并将所有的对象从较小的数组中拷贝到较大的数组中。
    写法:ArrayList<Employee> staff = new ArrayList<Employee>() = new ArrayList<>() (Employee可以省略)。
  • 对象包装器与自动打包
    (1)所有的基本类型都有一个与之对应的类,例子:int -- Integer;
    (2)对象包装器类是不可变的,并且是final的;
    (3)自动打包,编译器将自动地插入一条有关打包与拆包的指令;例如:
List<Integer> list = new ArrayList<Integer>();
list.add(3);          //<----> list.add(new Integer(3));
int n = list.get(i);  //<----> int n = list.get(i).intValue();
Integer n = 3; //3自动打包成Integer类型的对象 
n++;              //这里n不是基本类型

(4)对象包装类之间的比较也是调用equals()方法;
(5)包装器类常见方法:(引用PPT上例子)

int x = Integer.parseInt(s); //s为String类型,返回字符串表示的十进制数
int intValue(); //以int的形式返回Integer对象的值
static String toString(int i);
static Integer valueOf(String s); //返回s表示的整形数值进行初始化后的一个新的Integer对象

  • 参数数量可变的方法: Object... 类似可扩展数组(我的理解)
    实际的定义:(引用自PPT)

public PrintStream printf(String fmt, Object... args){
return format(fmt, args);
} //Object... 相当于 Object[]

  • 继承设计的技巧
    (1)将公共操作和属性放在父类;
    (2)不要使用protected修饰属性(破坏封装性);
    (3)使用继承时要确定是is-a关系,并确定所有继承的方法都有意义;
    (4)在覆盖方法时,注意不要改变预期的行为;
    (5)使用多态,而非类型信息(用instanceof判断时),可以使用abstract方法修饰可能变化的方法;
    (6)不要过多地使用反射(复杂)。

2. 书面作业

1. 代码阅读:Child压缩包内源代码

1.1 com.parent 包中 Child.java 文件能否编译通过?哪句会出现错误?试改正该错误。并分析输出结果。

Answer:
(1)com.parent包中Child.java文件不能编译通过。出错语句:

    public void getParenti(){
        System.out.println(i);
    }

如图所示:

(2)改正:

可以根据提示信息将i的声明改成protected,使子类可以调用父类的i。

(3)输出结果:

分析:

c.getParenti(); -> System.out.println(i); 输出父类中的i,初始化为1;
c.getParentj(); -> System.out.println(super.j); System.out.println(j); System.out.println(geti()); System.out.println(super.geti());(System.out.println(geti()); System.out.println(super.geti()); -> protected int geti(){return i;}) 输出子类继承父类中的j、父类中的j、父类中的i、子类继承父类中的i;
Other.showParentj(p); -> System.out.println(p.j); System.out.println(p.geti()); 输出父类的j、父类的i。

1.2 另外一个包中的 OutOfParentPackage.java,能否编译通过?提示什么错误?分析原因。如何更改才能使之正常编译?(写不出来正确答案不要紧,但请一定写出思考过程)

Answer:
(1)另外一个包中的OutOfParentPackage.java不能编译通过。提示的错误:The type Parent is not visible

原因:

Parent类默认访问权限是该包内的可以访问,而 OutOfParentPackage.java 不在 com.parent包中,显然不能访问。

(2)更改:

①  可以将 OutOfParentPackage.java 放入 com.parent包中;
②  根据提示,将 Parent类声明为 public,并将其相应的j、geti()属性声明为 public。

2. abstract进阶:阅读GuessGame抽象类的设计与使用源代码

2.1 Guess改造前代码很简单,而改造后的代码使用了抽象类、抽象方法看起来很复杂,那这样的改造到底有什么好处呢?

Answer:
改造前后的比较:

从代码中可以看出改造后的代码将输入输出改成了 abstract类。
正如改造前后标题所示:(引用自文件标题)

Guess(改造前,未使用抽象类,只能控制台输出)
GuessGame(改造后,使用抽象类,可以在控制台,也可以使用对话框图形界面等输入)

所以改造的好处:一般类虽然够用,但是定义抽象类可以随机选择你想要的执行环境或是想要具体实现的代码,确定好具体的执行环境后根据你想执行的方法重写方法或者添加其特点就ok了,不需要为每一个执行环境设计相应的代码来避免执行环境改变,也不需要为有相似特点的类一一重复实现。

2.2 如果想将该游戏改造成图形界面,应该进行一些什么操作?

Answer:

可以使用AWT 或者 SWING工具进行界面设计,使设计的界面继承抽象类,再重写抽象方法。

2.3 结合该例子,你觉得什么时候应该使用abstract?

Answer:
(引用自“抽象类什么时候用比较合适”)

并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象。

所以我认为,当方法或类要用于多种相似特性或不确定其执行环境时,可以用 abstract类。

2.4 重要:在这个例子中,变化的是什么,不变的是什么?尝试结合abstract、继承等概念进行说明。

Answer:

2.1中提过这个例子中是输入输出的执行环境待定,即输入输出是变化的;不变的应该是猜数字的方法。
这里的输入输出(抽象类)不能直接使用,必须选择一个执行环境的方法(或类)去实现abstract类,然后使用这个方法(或类)的实例;这里用到继承的思想。

3. Comparable与Comparator

3.1 描述Comparable接口的用途。为什么某个类实现了Comparable接口就可以直接使用Arrays.sort对其进行排序?

Answer:
(1)Comparable接口的用途:比较并排序。(补充)通过重写comparaTo()方法实现对对象的排序。

> 此接口强行对实现它的每个类的对象进行整体排序。 即实现对象的排序。

(引用是为了更好的解释,但是前提是自己理解。)

(2)原因:一个类实现了Comparable接口,说明它进行了整体排序,(补充)重写或者使用了comparaTo()方法,然后Arrays.sort(Object[] a)根据重写的方法进行顺序排序。(a - 要排序的数组)

Arrays.sort的功能:
PPT中的说明

对指定对象数组按升序进行排序, 数组中的所有元素都必须实现 Comparable 接口。

jdk文档中的说明:

根据元素的自然顺序对指定对象数组按升序进行排序。数组中的所有元素都必须实现 Comparable 接口。此外,数组中的所有元素都必须是可相互比较的(也就是说,对于数组中的任何 e1 和 e2 元素而言,e1.compareTo(e2) 不得抛出 ClassCastException)。
保证此排序是稳定的:不会因调用 sort 方法而对相等的元素进行重新排序。
ClassCastException - 如果数组包含不可相互比较的的元素(例如,字符串和整数)。

3.2 有了Comparable接口为什么还需要Comparator接口呢?

Answer:
Comparator接口:强行对某个对象集合进行整体排序的比较函数。
Comparable接口和Comparator接口都是java的一个接口, 并且是用来对自定义的类比较大小的;Comparable 定义在类的内部(内比较器),Comparator 是定义在类的外部的(外部添加的比较器)。

修改的Answer

Comparable接口虽然简便好用,但是形式单一,只能根据特定比较顺序进行排序;而Comparator接口(强行对某个对象集合进行整体排序的比较函数),在类外部重写compara()方法,可以传入需要比较的参数,根据重写的方法或顺序进行比较并排序,使用Arrays.sort(T[] a, Comparator<? super T> c)进行排序。
(a - 要排序的数组)
(c - 确定数组顺序的比较器。null 值指示应该使用元素的自然顺序)

我的引用:comparator接口与Comparable接口的区别

用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。

3.3 可选:使用匿名内部类、Lambda表达式实现PTA编程5-2。(未完成)

4. 面向接口案例分析____阅读Case-StudentDao.zip案例

4.1 画出类关系图,描述每个类与接口的作用。

Test类:调用执行。
Student类:属性->name,类型为String;+ Eclipse可以自动生成的Getters and Setter and toString()。
StudentDao接口:定义了三个抽象方法,分别为写入、读取和显示学生数据。
StudentDaoArrayImpl类:属性->students,类型为Student[];属性->size,类型为int;具体实现StudentDao接口的三个抽象方法 + 开辟"size"大小的数组。
StudenDaoListImpl类:属性->students,类型为List<Student>,具体实现StudentDao接口的三个抽象方法。

4.2 StudenDaoListImpl与StudentDaoArrayImpl有何区别?

Answer:

StudenDaoListImpl与StudentDaoArrayImpl的区别:
StudenDaoListImpl中用动态数组(可扩充) private List<Student> students = new ArrayList<Student>();
而StudentDaoArrayImpl中采用数组(默认大小) private Student[] students; 
但本质上都是使用数组。

5. 什么是面向接口编程?面向接口编程的好处是什么?____结合题目3与4(Test.java的代码)讨论分析。

Answer:
面向接口编程
面向接口编程详解(一)——思想基础

(1)面向接口编程:使用接口统筹各个类或对象的协作关系。
题目3中介绍Comparable与Comparator两种接口,都需用到Arrays.sort(),都可以比较排序,便于需要排序的算法使用。
题目4采用StudentDao接口,用于写入、读取、显示学生数据,统筹整个Test的执行。
(2)面向接口编程的好处:
①  便于修改(扩展或删除);
②  接口实现多态;
③  逻辑清晰,代码易懂。

6. 结对编程:面向对象设计(大作业2-非常重要)——待修改

内容:使用Java代码完成上周做的面向对象设计大作业,需要有初步界面。实现的功能尽量简单,少而精,只包含必要的功能,不要追求高大全。
写出:类图(尽量精简,不用太多子类)、系统常用功能描述、关键代码与界面
形式: 两人依托码云合作完成。请在这里贴出你们的学号、姓名与任务分工。
注意: 再过几次课要讲Java图形界面编程,到时候要将该系统升级为图形界面。系统的业务逻辑部分应该变化不大,变化大的是输入与输出部分。所以编码的时候,输入(Scanner)与输出(System.out)的代码,请不要将其与某个业务处理函数绑死。
选做加分: 给出两人在码云上同一项目的提交记录截图,额外加分。注:两个人在码云上新建一个项目。

6.1

学生A 学生B 项目地址
https://git.oschina.net/whting/ https://git.oschina.net/whting/java.git

6.2 常用功能描述框架图

6.3 关键代码

6.4 运行界面


3. 码云上代码提交记录及PTA实验总结(题目集:jmu-Java-04-面向对象2-进阶-多态接口内部类)

3.1. 码云代码提交记录——在码云的项目中,依次选择“统计-Commits历史-设置时间段”, 然后搜索并截图

3.2. PTA实验——实验总结

函数4-1:遇到问题:this不可以用到非静态,看题目的要求,不知道怎么修改打印的语句(System.out.println(this.getClass().getName());System.out.println(Arrays.toString(this.getClass().getInterfaces()));),做不出来。
编程5-1: 这题用的是 Comparable 接口,重写comparaTo()方法(这里用了老师上课说的方法)。 遇到的问题:sort放的位置不正确或说输出排序结果的方法使用不当。 解决:自己思考 + 询问同学。
编程5-2: 本题实现了 Comparator 接口,重写compara()方法(传入两个对象进行比较)。 遇到的问题:同第一题编程一样 + 粗心。 解决:粗心问题pta替我解决了(查看编译错误)

posted @ 2017-03-25 16:40  wuht  阅读(408)  评论(4编辑  收藏  举报