Java 继承

继承: 按照现有类的类型来创建新类,无需改变现有类的形式,采用现有类的形式并在其中添加新代码,这种神奇的方式称为继承.

继承是所有OOP语言和Java语言不可缺少的组成部分,当创建一个类时总是在继承,因此除非已明确指出要从其它类中继承,否则就是在隐式地从Java的标准根类Object进行继承.

继承是一种特殊的语法,在继承过程中,需要先声明新类和旧类相似.这种声明是通过在类主体的左边花括号之前,书写后面紧随基类名称的关键字extends而实现的.当这么做时,会自动得到基类中所有的域和方法.

组合和继承都能从现有类型生成新类型,组合一般是将现有类型作为新类型底层实现的一部分来可以实现的,而继承复用的是接口

下面是示例

package object;

class Cleanser{
    private String s = "Cleanser";//为了继承一般的潜规则时将所有的数据成员都指定为private,所有的方法都指定为public
    public void append(String a){s += a;}  // "+=" 将几个String对象连接成s
    public void dilute(){ append(" dilute() ");}
    public void apply() { append(" apply() ");}
    public void scrub() {append(" scrub()");}
    public String toString(){return s;}
    public static void main(String[] args) //可以在每个类中都创建一个main()方法,这种在
                                           //每个类中都设置一个main()方法的技术可使每个类的单元测试变得简单易行
                                           //而且在测试结束后也无需删除main(),可以将其留待下次测试
    {
        Cleanser x = new Cleanser();
        x.dilute();x.apply();x.scrub();
        System.out.println(x);
    }
}

public class Detergent extends Cleanser{  //extends 继承关键字
    //change a method
    public void scrub() //可以从新定义基类的scrub()方法
    {
        append(" Detergent.scrub()");
        super.scrub(); // Call base-class version 在scrub里调用scrub会产生递归,
                       //加super关键词表示超类的意思,当前类是从超类继承来的
    }
    // Add methods to the interface;
    public void foam() {append(" foam()");}
    //Test the new class
    public static void main(String args[])  //只有命令行调用的类的main()才会被使用,比如 java Cleanser test;
    {
        Detergent x = new Detergent();
        x.dilute();
        x.apply();
        x.scrub();
        x.foam();
        System.out.println(x);
        System.out.println("testing base class");
        Cleanser.main(args);
        
    }
}/* output:
Cleanser dilute()  apply()  Detergent.scrub() scrub() foam()
testing base class
Cleanser dilute()  apply()  scrub()
*///~

 同时使用继承和组合

package object;

class Plate{
    Plate(int i)
    {
        System.out.println("plae constructor");
    }
}
class DinnerPlate extends Plate{
    DinnerPlate(int i)
    {
        super(i);
        System.out.println("Dinnerplate constructor");
    }
}
class Utensil{ //器械
    Utensil(int i)
    {
        System.out.println("Utensil constructor");
    }
}
class Spoon extends Utensil{
    Spoon(int i)
    {
        super(i);
        System.out.println("Spoon constrcutor");
    }
}

class Fork extends Utensil{
    Fork(int i)
    {
        super(i);
        System.out.println("fork constructor");
    }
}
class Knife extends Utensil{
    Knife(int i)
    {
        super(i);
        System.out.println("knife constructor");
    }
}
//A cultural way of doing someting 有教养的去做事
class Custom{
    Custom(int i)
    {
        System.out.println("custom constructor"    );
    }
}

public class PlaceSetting extends Custom{
    private Spoon sp;
    private Fork frk;
    private Knife kn;
    private DinnerPlate pl;
    public PlaceSetting(int i)
    {
        super(i);
        sp  = new Spoon(i + 2);
        frk = new Fork(i + 3);
        kn  = new Knife(i + 4);
        pl  = new DinnerPlate(i = 5);
        System.out.println("PlaceSeting constructor");
    }
    public  static void main(String[] args )
    {
        PlaceSetting x = new PlaceSetting(9);
    }
}/* output:
custom constructor
Utensil constructor
Spoon constrcutor
Utensil constructor
fork constructor
Utensil constructor
knife constructor
plae constructor
Dinnerplate constructor
PlaceSeting constructor
*///:~

 二.向上转型:由导出类转型成基类,在继承图上是向上移动的,因此一般称为向上转型

"为新的类提供方法"并不是继承技术中最重要的方面,其最重要的方面是用来表现新类和基类之间的关系,这种关系可以用"新类是现有类的一种类型"这句话概括.

//: 这种将wind转化为instrument引用的动作,我们称之为向上转型.
package object;

class Instrument{
    public void play()
    {
    }
    static void tune(Instrument i)
    {
        i.play();
    }
}
public class Wind extends Instrument{
    public static void main(String[] args)
    {
        Wind wind = new Wind();
        Instrument.tune(wind);
    }
}

 三.用继承设计

1.在建立新类时如果首先使用继承,反而会加重我们的设计负担,使事情变得不必要复杂起来,

更好的方式是选择组合,尤其是在不确定使用哪种方式时,组合不会强制我们的程序设计进入继承的层次结构,而且更加灵活,因为它可以动态选择类型(因此也就选择了行为),相反,继承在编译时就需要知道确切的类型

一种通用的准则时"用继承表达行为的差异,并用字段表达状态的差异"

package object;

class Ship{
public void use(){}
}
class Attackship extends Ship{
public void use(){System.out.println("attack");} //通过继承得到两个不同的类,表达了use()方法的差异
}
class AlertStatus extends Ship{
public void use(){System.out.println("Alertstaus");}
}

public class Starship {
Ship ship = new Attackship();
public void change(){ship = new AlertStatus();} //通过组合使自己的状态发生变化,状态的变化也就产生了行为的变化
public void show(){ship.use();}
public static void main(String[] args)
{
Starship ss = new Starship();
ss.show();
ss.change();
ss.show();
}
}

 

posted @ 2018-12-22 20:52  江期玉  阅读(98)  评论(0编辑  收藏  举报