Java基本二:继承、实现

来源:互联网 发布:华为软件概要设计 编辑:程序博客网 时间:2024/05/15 11:59

       

        继承

        在上篇中说到将军类,士兵类。将军也是士兵类。拥有士兵的一些属性和方法。这种关系,用继承来表达。

继承:1、子类继承父类,子类拥有父类所有属性和方法。

            2、同时,子类可以重写父类的方法。父类可以声明 并且由子类来实现,也就是new 一个子类的类来被父类的声明指向,反之则不行。

            3、子类调用父类的方法,或者使用的属性不能是private所修饰的。

            4、继承只能单继承也就是一个子类只能继承一个父类。一个孩子只有一个父亲。

        士兵类:

        public class Soldier {

    protected String name;
    protected int age;
    protected String gunName;
    
    
    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }


    public int getAge() {
        return age;
    }


    public void setAge(int age) {
        this.age = age;
    }


    public String getGunName() {
        return gunName;
    }


    public void setGunName(String gunName) {
        this.gunName = gunName;
    }


    public void shoot(){
        System.out.println(age+"岁的"+name+"拿着"+gunName+"射击");
    }
}

        将军类:

        public class General extends Soldier{

    private int level;

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    
    public void command(Soldier soldier){
        System.out.println(level+"级别的"+name+"将军命令"+soldier.getName()+"开枪");
        soldier.shoot();
    }
    
}

        其中士兵类中的name、age、gunName属性都是protected了。受保护类型。将军类中集成了Soldier类,同时,代码比上一篇中的将军类少了许多。

        public class test {

     
    public static void main(String[] args) {
        
        Soldier soldier=new Soldier();
        soldier.setName("小明");
        soldier.setAge(18);
        soldier.setGunName("冲锋枪");
        
        General eGeneral=new General();
        eGeneral.setName("公爵");
        eGeneral.setAge(55);
        eGeneral.setGunName("手枪");
        eGeneral.setLevel(1);
        eGeneral.command(soldier);

        eGeneral.shoot();

        eGeneral.setGunName("毛瑟枪");

        eGeneral.shoot();

        Soldier general=new General();

     }
}
        输出:

    1级别的公爵将军命令小明开枪
    18岁的小明拿着冲锋枪射击
     55岁的公爵拿着手枪射击       


       方法重写:

      到这里又有问题了,将军和士兵都是拿着枪射击,但是将军跟士兵不一样啊。怎么办呢?进行重写方法。看将军类代码:

      public class General extends Soldier{

    private int level;

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    
    public void command(Soldier soldier){
        System.out.println(level+"级别的"+name+"将军命令"+soldier.getName()+"开枪");
        soldier.shoot();
    }
    
    @Override
    public void shoot() {
        // TODO Auto-generated method stub
        super.shoot();
        System.out.println("欢呼");
    }
    
}

        Oerride了shoot方法,加了一个注解标记@Override。当然也可以不加。其中的super.shoot();是执行一次父类的shoot()方法。将军和普通士兵一样开枪射击之后又欢呼一下。


        同名方法(多态)

        那么如果将军射击不想用自己的枪呢?用其他士兵的枪,也是射击,怎么办呢?。

    这样可以

         eGeneral.setGunName("毛瑟枪");   

        eGeneral.shoot();

       都是射击,那么可以给将军新增加一个同名方法。

        将军类:

public class General extends Soldier{

    private int level;

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }

    
    public void command(Soldier soldier){
        System.out.println(level+"级别的"+name+"将军命令"+soldier.getName()+"开枪");
        soldier.shoot();
    }
    
    @Override
    public void shoot() {
        // TODO Auto-generated method stub
        super.shoot();
        System.out.println("欢呼");
    }
    public void shoot(String gunName) {
        // TODO Auto-generated method stub
        this.gunName=gunName;
        shoot();
        System.out.println("欢呼");
    }
}

    

        都是shoot方法,却不冲突,这种就是Java里面的多态。

       多态:参数不同,方法名相同。参数不同,包括参数个数不同,包括参数类型不同。

        抽象类:

         当士兵分化越来越多,比如步兵,海兵、炮兵等。再用Soldier去new一个士兵的时候,就显的不知道这个士兵是什么士兵了。那么我们就规定这个Soldier类不能被new。它的实例只能是具体化的。这样就衍生了出了抽象类。

        1、 抽象类拥有普通父类拥有的所有特点。

         2、抽象类可以有抽象方法,abstract声明的方法,并且只能是在抽象类中声明,不能在抽象类中实现。

         3、抽象类不能被实例化,也就是不能被new 。抽象类只能声明。

        改过的抽象类:Soldier

        public abstract class Soldier {

    protected String name;
    protected int age;
    protected String gunName;
    
    
    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }


    public int getAge() {
        return age;
    }


    public void setAge(int age) {
        this.age = age;
    }


    public String getGunName() {
        return gunName;
    }


    public void setGunName(String gunName) {
        this.gunName = gunName;
    }


    public abstract void shoot();
}

      abstract 来修饰士兵类了。同时里面也有abstract来修饰的方法shoot();那么这个方法设计,也是抽象的,只能由它的继承类来重写,并且是必须重写,因为抽象化的方法也是不能被调用的。

       同时增加

public class SeaSoldier extends Soldier{

    public void sail(){
        System.out.println(age+"岁的"+name+"开船");
    }

    @Override
    public void shoot() {
        // TODO Auto-generated method stub
        System.out.println(age+"岁的"+name+"在水下拿着"+gunName+"射击");
    }
}

    海军士兵。有自己的方法开船也会重写士兵的射击。

测试代码中:

        SeaSoldier soldier=new SeaSoldier();
        soldier.setName("小明");
        soldier.setAge(18);
        soldier.setGunName("冲锋枪");
        soldier.sail();
        
        General eGeneral=new General();
        eGeneral.setName("公爵");
        eGeneral.setAge(55);
        eGeneral.setGunName("手枪");
        eGeneral.setLevel(1);
        eGeneral.command(soldier);
        eGeneral.shoot();

       

        因为SeaSoldier是一个士兵,所以将军也能命令他,还有一点,将军也能命令自己。抽象类、抽象方法说过了,有没有抽象属性呢?答:没有。同时抽象类有构造方法。但是没有抽象构造方法。

          接口

        慢慢走新的问题又会接着不断的到来,将军的命令,不可能只是命令开枪。还有可能命令士兵做其它事,比如命令士兵跑步等。而且能命令士兵的又不仅仅是将军,还有其它的角色,比如司令、政委。这些都是发命令的人。怎么去描述这样的问题呢,并且更加的符合思维。Java用接口来描述。命令者能执行指令方法,那么可以声明命令者接口。

public interface Commander {

    
    void commandShoot(Soldier soldier);
    void commandRun(Soldier soldier);
    
}

这里只是提取了各个角色的相类似的抽象行为,具体的行为,命令者不同,肯定实现也不同。

接口:1、接口可以说不是一个类。

             2、接口没有属性,只有声明的方法。

             3、接口必须不能被new 一个实例,因为接口也是抽象的,抽象的一系列的行为。

            4、接口声明的方法都是public的,默认是public,可以被abstract修饰,抽象的修饰。

            5、一个类可以实现多个接口。

将军类:

        public class General extends Soldier implements Commander{

    private int level;

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }
    
    @Override
    public void shoot() {
        // TODO Auto-generated method stub
        System.out.println("欢呼");
    }
    public void shoot(String gunName) {
        // TODO Auto-generated method stub
        this.gunName=gunName;
        shoot();
        System.out.println("欢呼");
    }

    @Override
    public void commandShoot(Soldier soldier) {
        // TODO Auto-generated method stub
        System.out.println(level+"级别的"+name+"将军命令"+soldier.getName()+"开枪");
        soldier.shoot();
    }

    @Override
    public void commandRun(Soldier soldier) {
        // TODO Auto-generated method stub
        System.out.println(level+"级别的"+name+"将军命令"+soldier.getName()+"跑步");
        soldier.run();
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println(age+"岁的"+name+"在大部队后面跑步");
    }

}

士兵类:

public abstract class Soldier {

    protected String name;
    protected int age;
    protected String gunName;
    
    public  Soldier(){
        
    }

    
    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
    }


    public int getAge() {
        return age;
    }


    public void setAge(int age) {
        this.age = age;
    }


    public String getGunName() {
        return gunName;
    }


    public void setGunName(String gunName) {
        this.gunName = gunName;
    }


    public abstract void shoot();
    public abstract void run();
}

海军士兵类:

public class SeaSoldier extends Soldier{

    public void sail(){
        System.out.println(age+"岁的"+name+"开船");
    }

    @Override
    public void shoot() {
        // TODO Auto-generated method stub
        System.out.println(age+"岁的"+name+"在水下拿着"+gunName+"射击");
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println(age+"岁的"+name+"在水下拿着"+gunName+"跑步");
    }
}

        那么为什么这么做呢?没减少代码,却增加了一个接口。这么说,在一个完整的军队系统中,将军类拥有士兵类的所有属性和方法,那么继承这个类,司令拥有将军所有的属性和方法,那么继承将军类。那么司令和将军又新增加了类似的外部方法,那么怎么办呢?显然司令类不能再继承了,如果士兵去继承,那么士兵不一定拥有这个属性或者方法,也不行,那么就引入了接口,这一次增加了命令系列方法,就让将军去实现命令接口。如果下次增加了其它的方法,同样去实现其它的接口。        那么继承将军类的类,或者间接集成将军类的类,就可以调用这些方法。

         命令者模式

        说到这里,将军命令士兵射击,命令士兵跑步,都是命令执行。那么这样的话commander只有一个命令执行的方法了。那么射击,跑步,就是命令所要执行的士兵的动作了。可以分为命令执行者,命令,和命令发出者。

   命令:

public interface Command {

    
   void commandExcute();
    
}

    跑步命令本身:
public class Run implements Command{

    
    private Soldier soldier;
    
    public Run(Soldier soldier) {
        super();
        this.soldier = soldier;
    }

    public Soldier getSoldier() {
        return soldier;
    }

    public void setSoldier(Soldier soldier) {
        this.soldier = soldier;
    }

    @Override
    public void commandExcute() {
        // TODO Auto-generated method stub

        System.out.println(soldier.name+"执行命令");      

         soldier.run();
        
    }

}
将军类:

public class General extends Soldier {

    private int level;

    public int getLevel() {
        return level;
    }

    public void setLevel(int level) {
        this.level = level;
    }
    
    @Override
    public void shoot() {
        // TODO Auto-generated method stub
        System.out.println("欢呼");
    }
    public void shoot(String gunName) {
        // TODO Auto-generated method stub
        this.gunName=gunName;
        shoot();
        System.out.println("欢呼");
    }
    public void shoot(int gunName) {
        // TODO Auto-generated method stub
        
        shoot();
        System.out.println("欢呼");
    }
    

    @Override
    public void run() {
        // TODO Auto-generated method stub
        System.out.println(age+"岁的"+name+"在大部队后面跑步");
    }

    
    public void executeCommand(Command command) {
        // TODO Auto-generated method stub

       System.out.println(age+"岁的"+name+"命令:");     

        command.commandExcute();
    }

}

将军只管执行命令,不必再关注是给哪位士兵命令了。由命令本身决定。

public class test {

    public static void main(String[] args) {
        
        SeaSoldier soldier=new SeaSoldier();
        soldier.setName("小明");
        soldier.setAge(18);
        soldier.setGunName("冲锋枪");
       
        General eGeneral=new General();
        eGeneral.setName("公爵");
        eGeneral.setAge(55);
        eGeneral.setGunName("手枪");
        eGeneral.setLevel(1);
        Run run=new Run(soldier);
        eGeneral.executeCommand(run);
    
    }
}

        输出:

55岁的公爵命令:
小明执行命令
18岁的小明在水下拿着冲锋枪跑步

          从上面可以看出,将军和海军士兵,是没有直接关系的。是命令让将军可以命令海军士兵执行命令。将军类只知道下达命令,海军士兵类也只是被动的执行自己的动作。







0 0