第六章 继承与多态html
所谓继承就是避免多个类间重复定义共同行为。java
1.重复在程序设计上就是很差的信号,若是要改进就能够把相同的程序代码提高为父类。linux
2.使用新的关键字extends表示继承而且扩充原先没有的行为。继承的好处就是若要修改,无需在继承的子类中去修改。
==注意==private成员会被继承,不过没法直接存取,必须经过父类提供的方法存取。git
3.子类只可继承一个父类,子类与父类之间会有is-a的关系。
例如:ide
Role role1 = new SwordsMan() SwordsMan swordsman = role1; //x SwordsMan swordsman = (SwordsMan)role1; //ok
第二条语句会出现编译错误。第三条语句在执行时会抛出classcastexception。函数
4.多态学习
使用单一接口操做多种类型的对象this
5.从新定义.net
定义与父类中相同的方法部署,但执行的内容不一样(override)。
在JDK5以后,内建标注设计
@Override
若是在子类的某个方法前标注,表示要求编译程序检查该方法是否是从新定义了父类的某个方法。
6.抽象方法,抽象类
若是某方法区块中真的没有任何程序的代码操做,可使用
abstract
标示该方法为抽象方法。
==注意==抽象类不能使用new生成对象
7.protected成员
相同包中的类能够直接存取,不一样包中的类能够在继承后的子类中直接存取。
public / package / protected / private
==提示==依照权限由小至大来区分就是private,无关键字,protected,与public。
8.从新定义的细节
若是想取得父类中的方法定义,能够在调用方法前加上super关键字。
可使用super调用父类方法,不能定义为private。
==注意==从新定义方法时,对于父类中的方法权限,只能扩大不能缩小。
9.再看构造函数
构造函数能够重载,父类中可重载多个函数。若是想执行父类中某构造函数,可使用super()指定。
==注意==this()与super()只能择一调用,并且要在构造函数第一行执行。
10.再看final关键字
class前也能够加上final关键字,表示这个类是最后一个类,不会再有子类,即就是不能被继承。
定义方法时,也可使用,表示子类不能够从新定义final方法。
11.java.lang.Object
若是继承时没有使用extends关键字指定任何类,那么继承的是java.lang.Object。
12.instanceof运算符能够用来断定对象是否由某个类建立,左操做数是对象,右操做数是类。
13.垃圾收集
没法经过变量引用的对象就是GC认定的垃圾对象。
垃圾回收前会调用finalize()方法,但因为调用时机没法肯定,建议不要使用finalize()方法。
1.使用接口(interface)定义行为
类要操做接口,必须使用implemnts关键字。
操做接口时,对接口中定义的方法有两种处理方式,一是操做接口定义的方法,二是再度将方法标示为abstract。
==继承与操做接口的区别==:继承时有“是一种”的关系,操做接口则表示“拥有行为”。
2.若是增长新的需求,原有的程序无需修改,只须要针对新需求撰写程序,就是有弹性,具备可维护性的程序
3.类能够操做的两个以上的类,也就是拥有两种以上的行为。
4.接口默认
在接口中枚举常数,必定要使用=指定值,不然编译错误。
==注意==要在类中定义枚举常数也是能够的,不过要明确写出public static final。
5.匿名内部类
在撰写java程序的时候,会面临临时继承某个类或操做某个接口并创建实例的需求,因为只使用一次,不须要定义名称。可使用匿名类。
在JDK8以前要在匿名内部类中存取局部变量,必须是final,不然编译错误。
==注意==局部变量的生命周期比对象短。java的作法是传值。
6.使用enum枚举常数
enum实际上定义了类,而enum中列举的常数,其实是public static final ,且为枚举类型实例,没法撰写程序直接实例化枚举类型,由于构造函数权限设定设定为private。
在第六章刚开始时,书上提到不能滥用继承,那么滥用继承会致使什么样的后果?
首先我上网搜索了一下怎么样才算滥用继承。
两个断定是不是滥用继承的重要依据:
1.若是一个类从核心用意和设计初衷上自然是另外一个类的子类,这种继承是天经地义的,并不存在破坏封装的说法。
2.在容许多继承的语言里,若是一个类须要使用到来自另外一个父类(特质)的“全体”字段和方法,或都反过来讲,把某个父类(特质)的全体成员赋予另外一个类时,若是从这两个类的设计用意和表明的概念上没有任何的违和感,那么,这时候使用继承也是正当的,没有破坏封装的嫌疑。
那么危害有哪些呢?
剑士:(Justin, 1, 200) 魔法师:(Monica, 1, 100)
而是出现以下错误:
class Role { private String name; private int level; private int blood; public int getBlood() { return blood; } public void setBlood(int blood) { this.blood = blood; } public int getLevel() { return level; } public void setLevel(int level) { this.level= level; } public String getName() { return name; } public void setName(String name) { this.name = name; } public void fight(){} } class SwordsMan extends Role{ public void fight(){ System.out.println("挥剑攻击"); } } class Magician extends Role{ //private String fight; public void fight(){ System.out.println("魔法攻击"); } public void cure(){ System.out.println("魔法治疗"); } } public class RPG3 { public static void main(String[] args) { SwordsMan swordsMan=new SwordsMan(); swordsMan.setName("Justin"); swordsMan.setLevel(1); swordsMan.setBlood(200); Magician magician=new Magician(); magician.setName("Monica"); magician.setLevel(1); magician.setBlood(100); drawFight(swordsMan); drawFight(magician); } static void drawFight(Role role){ System.out.println(role.getName()); role.fight(); } }
运行结果:
1.在同一个包(Array)中创建两个文件
2.并在两个代码段的开头都加入了
Package Array;
表示在同一个包中。
3.开始编译Guest代码段,出现错误
缘由:未先编译父类的方法。
4.先编译父类的方法ArrayList.java在编译Guest.java:
5.最后在运行时又出现了错误如上图
6.修改以下:须要将写上 package的名称.代码段名称
(而且运行)
问题解决~!
代码提交过程截图:
代码量截图:
脚本截图
缘由:linux的命令掌握的还不够熟练,不少命令由于不经常使用就容易忘记。
缘由:这个我如今也不太懂,但愿老师能讲解一下疑惑。
缘由:看书的时候这里没有仔细阅读,看书上给出的例子,不够熟练应用于实例中,还不够熟练掌握,作到触类旁通。
在第六章中了解了继承的目的,继承就是避免多个类间重复定义共同行为,而且在修改过程当中也避免了不少麻烦。还了解了多态与继承的关系,而且经过阅读教材大概知道了如何从新定义方法,从新定义时且若要取得父类中的方法定义,对于父类的方法权限,只能扩大但不能缩小。还知道了java.lang.Object是全部类追溯到最上层的父类。垃圾收集就是没法经过变量参考的对象,就是GC认定的垃圾对象。在第七章中,举例子介绍了接口定义行为,了解了接口的多态操做。两种方法的枚举常数。
此次考试比前两次的成绩提升了2分,很开心。由于此次看书看得比较仔细,因此翻书找的时候没有浪费太多时间,因此时间上相对充裕了,题也写完了。还须要在代码上多下功夫,作到天天都要敲代码。
public class Role { private String name; private int level; private int blood; public int getBlood() { return blood; } public void setBlood(int blood) { this.blood=blood; } public int getLevel() { return level; } public void setLevel(int level){ this.level=level; } public String getName() { return name; } public void setName(String name) { this.name=name; } }
接着使用SwordsMan能够以下继承:
==出现了新的关键字extends==,表示会扩充Role的行为,也就是继承,扩充了本来没有的fight行为。
Magician也能够进行继承:
p178页 定义的ArrayList类,能够不限长度收集对象,每次收集的对象会放在next索引处,使用size()方法得知已收集的对象个数。
==注意==若是使用无参数构造函数,则默认容量为16。
p186
定义的抽象类,这个类是不完整的,因此显示输入输出就不能操做。
p187继承抽象类GuessGame:
将3个代码段放在同一个包下(Iheritance)
p186-187猜数字程序
也是将代码片断放在同一个package中,而后分别编译,最后运行。
p197-201
Oceanworld程序,了解了接口和继承的区别,以及优点。并了解了
interface
implements
关键字的定义及用法。继承会有“是一种”关系,操做接口则表示“拥有行为”因此会优先考虑接口而不是继承。
课本编海洋的程序:
在输入p202页Airplane代码段时
课本上代码出现错误:
package OceanWorld1; public class Seaplane implements Swimmer,Flyer { private String name; public Seaplane(String name) { this.name = name; } @Override public void fly() { System.out.printf("海上飞机 %s 在飞%n", name); } @Override public void swim() { System.out.printf("海上飞机 %s 航行海面%n", name); } }
按照课本输入的Airplane.java可是代码为:
public class Seaplane ....
因此从新创建文件名,并进行编译,以下修改编译正确:
p209页程序:
p216
使用了匿名内部类。
与209页程序做对比,使用enum定义,不像以前play()方法能够传入任何int值,因此不须要使用default进行检查。
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 15/15 | 1/1 | 23/26 | |
第二周 | 208/240 | 2/2 | 35/38 | |
第三周 | 376/584 | 3/3 | 32/38 | |
第四周 | 823/1407 | 4/4 | 28/30 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进本身的计划能力。这个工做学习中很重要,也颇有用。
耗时估计的公式
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。
计划学习时间:28小时
实际学习时间:30小时