复用类

组合语法

我们看一个例子:

class WaterSource {
    private String s;
    WaterSource() {
        System.out.println("WaterSource()");
        s = "Constructed";
    }
    public String toString() {
        return s;
    }
}

public class SprinklerSystem {
    private String valve1, valve2, valve3, valve4;
    private WaterSource source = new WaterSource();
    private int i;
    private float f;
    public String toString() {
        return  "valve1 = " + valve1 + " " +
                "valve2 = " + valve2 + " " +
                "valve3 = " + valve3 + " " +
                "valve4 = " + valve4 + "\n" +
                "i = " + i + " " + " f = " + f + " " + "source = " + source;
    }
    public static void main(String[] args) {
        SprinklerSystem sprinklers = new SprinklerSystem();
        System.out.println(sprinklers);
    }
}

在这段代码中,我们可以看到,每一个非基本类型的对象都有一个toString() 方法,并且当编译器需要一个String,而你只有一个对象时,该方法就会被调用。
System.out.println();中需要的是一个String,但是你只有一个对象,并且这个对象有一个toString() 方法,该方法会被调用。
再进一步的,"source = " + source 中,source是一个对象,由于只能将一个String对象和String对象进行相加,所以,source中的toString() 将会被调用。

继承语法

继承是为了使用一个已经存在的类的定义作为基础,新类的定义可以添加新的数据和新的方法,也可以用父类的功能。继承可以很容易复用的代码。继承是为了重用父类代码,同时为实现多态性做准备(待理解)。
我们看一个例子:

class CLeanser {
    private String s = "Cleanser";
    public void append(String a) {
        s += a;
    }
    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) {
        CLeanser x = new CLeanser();
        x.dilute();
        x.apply();
        x.scrub();
        System.out.println(x);
    }
}

public class Detergent extends CLeanser {
    //change a method
    public void scrub() {
        append(" Detergent.scrub()");
        super.scrub(); //call base-class version
    }
    //add methods to the interface
    public void foam() {
        append(" foam()");
    }
    //test the new class
    public static void main(String[] args) {
        Detergent x = new Detergent();
        x.dilute();
        x.apply();
        x.scrub();
        x.foam();
        System.out.println(x);
        //test the bas class
        System.out.println("Test the base class");
        CLeanser.main(args);
    }
}

1、使用了 += 重载操作符
2、每一个类中都有main方法(单元测试)
3、只有命令行调用的那个类的main方法才会被调用
4、即使一个类不是public类,如果命令行是java Cleanser,那么Cleanser.main(),任然可以被调用。即使一个类中只有包的访问权限,其public main也是可以访问的。
5、在这个例子中,Detergent.main 明确调用了CLeanser.main,并且从命令行获取参数传递给CLeanser.main,当然也可以传递任意String数组。
6、Cleanser中的所有方法都必须是public的,这一点很重要。如果没有任何访问权限修饰,那么成员默认的访问权限是包访问权限,仅仅允许包内成员访问。但是包中的都一个类要从Cleanser中继承,则只能访问public成员。所以,为了继承,一般的规则就是将所有的数据成员指定为private,所有的方法指定为public。
7、在Cleanser接口中的一组方法:append(), dilute(), apply(), scruc()和toString()。由于Detergent是通过关键字extends从Cleanser中导出的,所以它可以其接口中自动获取这些方法,尽管并不能真正看到这些方法在Detergent中的显式定义。因此,继承视作为对类的复用。
8、在scrub()中可见,使用基类中定义的方法及对他进行修改是可行的。在此例中,你可能想要在新版本中调用从基类继承而来的方法。但是在scrub中并不能直接调用scrub,这样会产生递归。因此,Java中通过super关键字表示超类,就是当前类是从超类继承而来的。表达式super.scrub将调用基类版本的scrub方法。
9、在继承的过程中,并不一定非要使用基类的方法,也可以咋导出类中添加新方法。比如foam()

初始化基类

看一个例子:

class Art {
    Art() {
        System.out.println("Art constructor");
    }
}

class Drawing extends Art {
    Drawing() {
        System.out.println("Drawing constructor");
    }
}

public class Cartoon extends Drawing {
    public Cartoon() {
        System.out.println("Cartoon constructor");
    }
    public static void main(String[] args) {
        Cartoon x = new Cartoon();
    }
}

output:
Art constructor
Drawing constructor
Cartoon constructor
我们通过在构造函数中打印调试信息,来观察构造的过程。于是发现,构建过程是从基类向外扩散的。

代理

在看一个例子
例如太空船需要一个控制模块:

class SpaceShipControls {
    void up(int velocity) {};
    void down(int velocity) {};
    void left(int velocity) {};
    void right(int velocity) {};
    void forward(int velocity) {};
    void back(int velocity) {};
    void turboBoost() {};
}

public class SpaceShip extends SpaceShipControls {
    private String name;
    public SpaceShip(String name) {
        this.name = name;
    }
    public String toString() {
        return name;
    }
    public static void main(String[] args) {
        SpaceShip ship = new SpaceShip("GM-JIANG DE SPACESHIP");
        ship.forward(100);
    }
}

这里我们使用了继承的方法。更准确的说SpaceShip包含了SpaceShipControls,于此同时SpaceShipControls的所有方法在SpaceShip中都暴露出来了。
下面用代理来解决此题:

class SpaceShipControls1 {
    void up(int velocity) {};
    void down(int velocity) {};
    void left(int velocity) {};
    void right(int velocity) {};
    void forward(int velocity) {};
    void back(int velocity) {};
    void turboBoost() {};
}

public class SpaceShipDelegation {
    private String name;
    private SpaceShipControls1 controls = new SpaceShipControls1();
    public SpaceShipDelegation(String name) {
        this.name = name;
    }
    //Delegation methon
    public void back(int velocity) {
        controls.back(velocity);
    }
    public void down(int velocity) {
        controls.down(velocity);
    }
    public static void main(String[] args) {
        SpaceShipDelegation ship = new SpaceShipDelegation("GM-JIANG DE SPACESHIP");
        ship.back(100);
    }
}

可以看到,上面的方法是如何传递给了底层的controls对象的,而其接口由此也就与使用继承得到的接口相同了。但是,我们使用代理时可以拥有更多的控制力,因为我们可以选择只提供在成员对象中的方法的某个子集。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值