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

代码托管截图

参考资料

posted @ 2016-03-27 17:12  145223  阅读(171)  评论(2编辑  收藏  举报