20145223《Java程序程序设计》第4周学习总结
20145223 《Java程序设计》第4周学习总结
教材学习内容总结
面向对象中,子类继承父类避免重复的行为定义,不过并不是为了避免重复定义行为就使用继承。程序代码重复在以后修改代码的时候会产生许多重复的步骤,所以我们可以将多个类间重复的相同的程序代码提升为父类。例如书上158页和159页的例子,两个代码之间有许多相同的部分,因此我们就可以把这样的代码提取出来提升为父类。
package role;
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 String getName(){
return name;
}
public void setName(){
this.name=name;
}
}
SwordsMan就可以通过下面这样的形式,继承拥有Role中的内容,并进行扩充
class SwordsMan extends Role{
public void fight(){
System.out.println("挥剑攻击");
}
}
虽然Swordsman中没有定义Role中的方法,但是通过继承Role就可以拥有这些方法直接进行使用,而且在修改程序的时候,只需要对Role的内容进行修改。
Role role1=new Swordsman();
SwordsMan swordsMan=role1;
这个程序片段的第一行可以通过编译,但是第二行会显示编译失败,这是因为SwordsMan是一种Role,但是Role不一定是一种SwordsMan,编译程序会检查父类与子类之间的这种“是一种”关系。但是如果你想要让Role扮演SwordsMan,那么编译程序就不会再提示,程序就能得到编译,只不过运行结果不一定会成功就是了。
SwordsMan SwordsMan=(SwordsMan)role1;
在书上的例子中,我们在Role类里定义了figth()的方法,但是具体的方法我们要在继承Role的子类中进行定义:
public class SwordsMan extends Role{
public void fight()
{
System.out.println("挥剑攻击");
}
}
也就是说在继承父类之后定义与父类中相同的方法部署,执行内容不同时,需要重新定义。在重新定义父类中某个方法的时候,子类必须撰写与父类方法中相同的签署。
如果某方法区块中真的没有任何代码程序操作,可以使用abstract标示该方法为抽象方法:
public abstract void fight();
继承语法细节:
定义 toString()方法,可以让程序在撰写的时候更加简洁
public String toString(){
return String.format("剑士(%s,%d,%d)%n",this.getName(),this,getLevel(),this.getBlood());
}
这样客户端的撰写方式就可以简化为:
System.out.println(swordsMan.toString());
因为Role中name已经被定义为private,因此如果我们想要在子类中直接存取name这样的类型时,就将它们定义为protected:(被定义为protected的成员,相同包中的类可以直接存取,不同包中的类可以在继承后的子类中直接存取)
public abstract class Role{
protected String name;
……
}
定义后,原本的代码就可以改写为
public String toString(){
return String.format("剑士(%s,%d,%d)%n",this.name,this,level,this.blood);
}
父类中可重载多个构造函数,如果子类构造函数没有指定执行父类中哪个构造函数,默认调用的就是父类中无参数构造函数
class Some{
Some(){
System.out.println("调用Some()");
}
}
class Other extends Some{
Other(){
super();
System.out.println("调用Other()");
}
}
在执行new Other()时,先执行的Other()中的流程,而Other()中指定调用父类中无参数构造函数,再执行super()后的流程。
final可以指定变量值不再改变,在class前加上final,意思是这个类是最后一个类,不会再有子类,即不能被继承。限定方法为final表示最后一次定义该方法,子类不能重新定义。
在Java中子类只能继承一个父类,没有使用extends关键字指定继承的类时,继承java.lang.Object。
程序1:
public class Some{
……
}
相当于程序2:
public class Some extends Object{
……
}
注意:java.lang.Object是所有类的顶层父类,在Java中任何类追溯至上层父类,一定是java.lang.Object。
“定义行为”,在Java中可使用interface关键字定义:
public interface Swimmer{
public abstract void swim();
}
类要操作接口,必须使用implements关键字,操作某接口时有两种处理方式:1、操作接口中定义的方法 2、再度将该方法标记为abstract。这里用的是第二种方法:
public class Human implements Swimmer{
private String name;
public Human(String name){
this.name =name;
}
public String getName(){
return name;
}
@Override
public void swim(){
System.out.printf("人类 %s 游泳 %n",name);
}
}
Human操作了Swimmer,但是没有继承Fish,但是拥有Swimmer的行为.
在Java中继承的关系是“是一种”关系,而操作接口表示的是“拥有行为”,两者的关系是不一样的,在判断借口多台语法的时候,按照“右边是不是拥有左边的行为”或者“右边对象是不是操作了左边接口”来进行判断。
接口语法细节:1、接口默认:我们使用interface定义抽象的行为和外观,接口中的方法可以声明为public abstract:
public interface Swimmer{
public abstract void awim();
}
为了方便可以省略public abstract:
public interface Swimmer{
void awim();
}
2、在接口中枚举常数,一定要使用=指定值,否则编译就会出错。
3、接口可以继承别的接口,也可以同时继承两个以上的借口,也是使用了extend关键字,表示继承父接口的行为。
4、匿名内部类:临时继承某个类或操作某个接口并建立实例,不需要为这些类定义名称,用匿名内部类解决需求,以下面的程序为例:
Object o=new Object(){
@Override
public String toString(){
return"XXX";
}
};
如果是操作某个接口,例如Some接口定义了doService()方法,建立匿名类实例如下:
package axiba;
Some some =new some(){
public void doService(){
System.out.println("XXX");
}
};
5、enum语法:可以用于定义枚举常数,enum定义了特殊的类,继承自java.lang.Enum,由编译程序处理,直接撰写程序继承Enum类会被编译程序拒绝。
教材学习中的问题和解决过程
在学习继承的过程中,我在编译程序上随便敲了几行代码,用来检查多态语法逻辑的正确性,按照书上所说本来应该会出现ClassCastException这一个错误,我在修改了代码过后程序依然不能运行。仔细检查过后我没有发现语法上的错误,但视却发现了我无意间敲多了一个父类,然后我又在书上P188页找到了这样一句话:“在Java中,子类只能继承一个父类。”我又翻回书本前面的内容,发现我在看书的时候遗漏了书上P162页下面的一模一样的一句话。认识到了自己看书不仔细导致的错误之后,将程序进行修改,程序就可以运行了。
代码调试中的问题和解决过程
将书上p158至p159中的代码整合成一个完整的程序时,出现了这样的错误:
编译程序告诉我在继承共同行为.magician中创建方法setBlood(int)
我按照编译程序的提示对代码进行了调整,程序就没有显示有错误:
并且程序也能正常运行:
其他(感悟、思考等,可选)
我感觉这一周的学习比上一周的更加难了,书上有很多专业的术语一开始我并不是十分理解,就算看了书以后也还是似懂非懂。但是在把树上的代码亲手敲到电脑上运行以后,感觉很快就能理解程序的意思。而且在一点点敲代码的过程中,有时候还会发现自己没有注意到的一些小细节,同时也会思考为什么要这样去写代码。在不断地深入学习以后,我觉得仅仅是照搬书上的代码已经不能很好地去理解这些知识。虽然看起来已经知道了是怎么一回事,但是当我自己想尝试着去写一些代码时,就发现有些地方自己还是云里雾里。所以只有真正实践了,才能更好地去发现问题和解决问题。同时,我发现在学习的过程中,有些问题书上是没有给出答案的,但是当我把这样的问题放到网上的时候,网上就会给出很多有用的资源,很多我遇到的问题别人也已经遇到过,我犯下的错误别人也早就经历了类似的错误。所以我觉得在以后的学习中,不需要过分在意自己所犯的错误,也不要害怕出现问题,很多问题并不是只有我一个人会犯,许多问题前人已经给出了解决的方法,当你实在不知道问题出在哪的时候,百度一下,或许问题也就引刃而解。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 4000行 | 20篇 | 400小时 | |
第一周 | 200/200 | 1/1 | 15/12 | |
第二周 | 180/500 | 1/1 | 18/12 | |
第三周 | 600/1000 | 1/1 | 17/16 | |
第四周 | 400/1300 | 1/1 | 16/15 |