8.代码复用

复用

8.3委托

Java不直接支持的第三种重用关系称为委托。这介于继承和组合之间,因为将一个成员对象放在正在构建的类中(比如组合),但同时又在新类中公开来自成员对象的所有方法(比如继承)。例如,宇宙飞船需要一个控制模块:

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 SpaceShipDelegation {
    private String name;
    private SpaceShipControls controls = new SpaceShipControls();

    public SpaceShipDelegation(String name) {
        this.name = name;
    }

    // Delegated methods:
    public void up(int velocity) {
        conrols.up(velocity);
    }

    public void down(int velocity) {
        conrols.down(velocity);
    }

    public void left(int velocity) {
        conrols.left(velocity);
    }

    public void right(int velocity) {
        conrols.right(velocity);
    }

    public void forward(int velocity) {
        conrols.forward(velocity);
    }

    public void back(int velocity) {
        conrols.back(velocity);
    }

    public void turboBoost() {
        conrols.turboBoost();
    }

    public static void main(String[] args) {
        SpaceShipDelegation protector = new SpaceShipDelegation("NSEA Protector");

        protector.forward(100);
    }
}
8.4结合组合与继承
8.4.1保证适当的清理

有时,类可能在其生命周期中执行一些需要清理的活动。由于无法知道垃圾收集器何时会被调用,甚至它是否会被调用。因此,如果想为类清理一些东西,必须显式地编写一个特殊的方法来完成它,并确保客户端程序员知道他们必须调用这个方法。例如,在屏幕上绘制图片的计算机辅助设计系统:

// Ensuring proper cleanup
class shape {
    Shape(int i) {
        System.out.println("Shape constructor");
    }

    void dispose() {
        System.out.println("Shape dispose");
    }
}

class Circle extends Shape {
    Circle(int i) {
        super(i);
        System.out.println("Drawing Circle");
    }

    @Override
    void dispose() {
        System.out.println("Erasing Circle");
        super.dispose();
    }
}

class Triangle extends Shape {
    Triangle(int i) {
        super(i);
        System.out.println("Drawing Triangle");
    }

    @Override
    void dispose() {
        System.out.println("Erasing Triangle");
        super.dispose();
    }
}

class Line extends Shape {
    private int start, end;
    Line(int start, int end) {
        super(start);
        this.start = start;
        this.end = end;
        System.out.println("Drawing Line: " + start + ", " + end);
    }

    @Override
    void dispose() {
        System.out.println("Erasing Line: " + start + ", " + end);
        super.dispose();
    }
}

public class CADSystem extends Shape {
    private Circle c;
    private Triangle t;
    private Line[] lines = new Line[3];

    public CADSystem(int i) {
        super(i + 1);

        for (int j = 0; j < lines.length; j++) {
            lines[j] = new Line(j, j * j);
        }

        c = new Circle(i);
        t = new Triangle(i);

        System.out.println("Combined constructor");
    }

    @Override
    public void dispose() {
        System.out.println("CADSystem.dispose()");
        // The order of cleanup is the reverse of the order of initialization
        t.dispose();
        c.dispose();

        for (int i = lines.length; i >= 0; i--) {
            lines[i].dispose();
        }

        super.dispose();
    }

    public static void main(String[] args) {
        CADSystem x = new CADSystem(47);

        try {
            // Code and exception handling...
        } finally {
            x.dispose();
        }
    }
}
8.5组合与继承的选择

当想在新类中包含一个已有类的功能时,使用组合,而非继承。也就是说,在新类中嵌入一个对象(通常是私有的),以实现其功能。新类的使用者看到的是所定义的新类的接口,而非嵌入对象的接口。
有时,让类的用户直接访问到新类中的组合成分是有意义的。只需将成员对象声明为public即可(可以把这当做半委托的一种)。成员对象隐藏了具体实现,所以这是安全的。当用户知道正在组装一组部件时,会使得接口更加容易理解。

是一个的关系是用继承来表达的,而有一个的关系则用组合来表达。

8.7向上转型

因为是从一个更具体的类转化为一个更一般的类,所以向上转型永远是安全的。也就是说,派生类是基类的一个超集。它可能比基类包含更多的方法,但它必须至少具有与基类一样的方法。在向上转型期间,类接口只可能失去方法,不会增加方法。这就是为什么编译器在没有任何明确转型或其他特殊标记的情况下,仍然允许向上转型的原因。

8.7.1再论组合和继承

继承其实不太常用,除非确实使用继承是有帮助的。一种判断使用组合还是继承的最清晰的方法是问一问自己是否需要把新类向上转型为基类。

8.8final关键字
8.8.1final数据

一个被staticfinal同时修饰的属性只会占用一段不能改变的存储空间。
当用final修饰对象引用而非基本类型时,其含义会有一点令人困惑。对于基本类型,final使数值恒定不变,而对于对象引用,final使引用恒定不变。一旦引用被初始化指向了某个对象,它就不能改为指向其他对象。但是,对象本身是可以修改的,java没有提供将任意对象设为常量的方法。这一限制同样适用于数组,数组也是对象。

8.9类初始化和加载

每个类的编译代码都存在于它自己独立的文件中。该文件只有在使用程序代码时才会被加载。一般可以说类的代码在首次使用时加载。这通常是指创建类的第一个对象,或是访问了类的static属性或方法。构造器也是一个static方法尽管它的static关键字是隐式的。因此,准确地说,一个类当它任意一个static成员被访问时,就会被加载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码复用是指在编程过程中,通过使用已有的代码来实现相同或类似的功能,从而减少代码的重编写和维护工作。在Python中,有多种方式可以实现代码复用,包括函数、模块和类等。 1. 函数复用: 函数是一段可重使用的代码块,可以通过定义函数来实现代码复用。可以将一段需要重执行的代码封装在函数中,并在需要的地方调用该函数。下面是一个简单的示例: ```python def add(a, b): return a + b result = add(3, 4) print(result) # 输出:7 ``` 2. 模块复用: 模块是一个包含了一组相关函数、类和变量的文件,可以通过导入模块来实现代码复用。Python提供了丰富的标准库和第三方库,可以直接使用这些库中的函数和类。下面是一个使用标准库中的random模块的示例: ```python import random num = random.randint(1, 10) print(num) # 输出:随机生成的1到10之间的整数 ``` 3. 类复用: 类是一种面向对象的编程方式,可以通过定义类来实现代码复用。类可以封装数据和方法,并通过创建对象来使用这些数据和方法。下面是一个简单的类的示例: ```python class Person: def __init__(self, name): self.name = name def say_hello(self): print("Hello, my name is", self.name) person = Person("Alice") person.say_hello() # 输出:Hello, my name is Alice ``` 通过继承可以实现类的复用,子类可以继承父类的属性和方法,并可以在子类中添加新的属性和方法。下面是一个继承的示例: ```python class Student(Person): def __init__(self, name, grade): super().__init__(name) self.grade = grade def say_grade(self): print("I am in grade", self.grade) student = Student("Bob", 5) student.say_hello() # 输出:Hello, my name is Bob student.say_grade() # 输出:I am in grade 5 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值