• Thinking in java Chapter7 复用类


    组合 新类中产生 现有类的对象
    继承 现有类的形式并其中添加新代码

    7.1组合语法

    将对象置于新类:直接定义基本类型;非基本类型对象,引用置于新类;

    package chapter7reusing;
    // Composition for code reuse.
    
    class WaterSource {
        private String s;
    
        WaterSource() {
            System.out.println("WaterSource()");
            s = "Constructed";
        }
    
        public String toString() { //每一个非基本类型对象都有 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 + " " +
                            "i = " + i + " " +
                            "f = " + f + " " +
                            "source = " + source;//调用toString(),将source对象转换为String
        }
    
        public static void main(String[] args) {
            SprinklerSystem sprinklerSystem = new SprinklerSystem();
            System.out.println(sprinklerSystem); // 基本类型 初始化为0 对象引用初始化为null
        }
    }
    /* outpub:
    WaterSource()
    valve1 = null valve2 = null valve3 = null valve4 = null i = 0 f = 0.0 source = Constructed
    

    四种方式初始化

    1. 定义对象的地方
    2. 类的构造器
    3. 惰性初始化
    4. 使用实例初始化
    package chapter7reusing;
    //Constructor initialization with composition
    
    import static chapter6access.Print.print;
    
    class Soap {
        private String s;
    
        Soap() { // 类的构造器中
            print("Soap()");
            s = "Constructed";
        }
    
        public String toString() {
            return s;
        }
    
    }
    
    public class Bath {
        private String //定义对象的地方初始化,构造器被调用之前初始化
                s1 = "Happy",
                s2 = "Happy",
                s3, s4;
        private Soap castille;
        private int i;
        private float toy;
    
        public Bath() {
            print("Inside Bath()");
            s3 = "Joy";
            toy = 3.14f;
            castille = new Soap(); // 使用实例初始化
        }
    
        {
            i = 47;
        }
    
        public String toString() {
            if (s4 == null) //惰性初始化:使用对象之前初始化
                s4 = "Joy";
            return
                    "s1 = " + s1 + "
    " +
                            "s2 = " + s2 + "
    " +
                            "s3 = " + s3 + "
    " +
                            "s4 = " + s4 + "
    " +
                            "i = " + i + "
    " +
                            "toy = " + toy + "
    " +
                            "castille = " + castille;
        }
    
        public static void main(String[] args) {
            Bath bath = new Bath();
            print(bath);
        }
    
    }
    
    

    惰性初始化 实例第一个类的对象

    package chapter7reusing;
    
    class First {
        String s;
    
        public First(String si) {
            System.out.println("FirstClass()");
            s = si;
        }
    
        public String toString() {
            return s;
        }
    
        public void setString(String sNew) {
            s = sNew;
        }
    
    }
    
    class Second {
        String s;
        First first;
    
        public Second(String si) {
            s = si;
        }
    
        public void check() {
            if (first == null)
                System.out.println("not initialized");
            else
                System.out.println("initialized");
        }
    
        private First lazy() {
            if (first == null) {
                System.out.println("create first");
                first = new First(s);
            }
            return first;
        }
    
        public First getFirst() {
            return lazy();
        }
    
        public String toString() {
            return lazy().toString();
        }
    
        public void setFirst(String s) {
            lazy().setString(s);
        }
    }
    
    public class E01_Composition {
        public static void main(String[] args) {
            Second second = new Second(("init String"));
            second.check();
            System.out.println(second.getFirst());
            second.check();
            System.out.println(second);
            second.setFirst("New String");
            System.out.println(second);
        }
    } /* Output:
    not initialized
    create first
    FirstClass()
    init String
    initialized
    init String
    New String
    */
    

    7.2继承语法

    隐式继承 标准根类Object

    package chapter7reusing;
    // Inheritance syntax & properties.
    
    import javax.swing.*;
    
    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) {  //每个类中设置main方法  单元测试简便易行,无需删除
            Cleanser cleanser = new Cleanser();
            cleanser.dilute();
            cleanser.apply();
            cleanser.scrub();
            System.out.println(cleanser);
        }
    
    }
    
    class NewDetergent extends Detergent {
        // 覆盖scrub()
        public void scrub() {
            append("NewDetergent.scrub()");
            super.scrub();
        }
        // 增加方法
        public void sterilize(){ //灭菌
            append(" sterilize()");
        }
    
        public static void main(String[] args) {
            NewDetergent newDetergent = new NewDetergent();
            newDetergent.dilute();
            newDetergent.apply();
            newDetergent.scrub();
            newDetergent.foam();
            newDetergent.sterilize();
            System.out.println(newDetergent);
        }/* Output:
        Cleanser dilute() apply()NewDetergent.scrub() Detergent.scrub() scrub() foam() sterilize()
        */
    }
    
    public class Detergent extends Cleanser {
        // 更改方法
        public void scrub() {
            append(" Detergent.scrub()");
            super.scrub(); //调用基类
        }
    
        // 增加接口方法
        public void foam() {
            append(" foam()");
        }
    
        //测试新类
        public static void main(String[] args) {
            Detergent detergent = new Detergent();
            detergent.dilute();
            detergent.apply();
            detergent.scrub();
            detergent.foam();
            System.out.println(detergent);
            System.out.println("Testing base class:");
            Cleanser.main(args);
        }
    }/* Output:
    Cleanser dilute() apply() Detergent.scrub() scrub() foam()
    Testing base class:
    Cleanser dilute() apply() scrub()
    */
    
    

    7.2.1 初始化基类

    基类 导出类
    创建一个导出类的对象时,该对象也包含一个基类的子对象。
    在构造器中调用基类构造器进行初始化。基类构造器具有初始化基类的能力。

    package chapter7reusing;
    
    
    class Art {
        Art() {
            System.out.println("Art constructor");
        }
    }
    
    class Drawing extends Art {
        Drawing() {
            System.out.println("Drawing constructor");
        }
    
    }
    
    public class Cartoon extends Drawing {
        Cartoon() { 
            System.out.println("Cartoon constructor");
        }
    
        public static void main(String[] args) {
            Cartoon x = new Cartoon();
        }
    }/* Output: 构建过程 从 基类 向外 扩散
    Art constructor
    Drawing constructor
    Cartoon constructor
    */
    
    
    package chapter7reusing;
    
    class ClassA {
        ClassA() {
            System.out.println("ClassA()");
        }
    }
    
    class ClassB {
        ClassB() {
            System.out.println("ClassB()");
        }
    }
    
    class ClassC extends ClassA {
        ClassB classB = new ClassB();
    }
    
    public class E05 {
        public static void main(String[] args) {
            ClassC classC = new ClassC();
        }
    }/* Output 先调用基类构造方法,然后是成员对象的构造方法
    ClassA()
    ClassB()
    */
    

    带参数的构造器

    必须关键字 super显示调用基类构造器,并适当的参数列表

    package chapter7reusing;
    
    class Game {
        Game(int i) {
            System.out.println("Game Constructor");
        }
    }
    
    class BoardGame extends Game {
        BoardGame(int i) {
            super(i);
            System.out.println("BoardGame constructor");
        }
    }
    
    public class Chess extends BoardGame {
        Chess() {
            super(11);
            System.out.println("Chess Constructor");
        }
    
        public static void main(String[] args) {
            Chess chess = new Chess();
        }
    }/* Output
    Game Constructor
    BoardGame constructor
    Chess Constructor
    */
    

    7.3 代理

    public class SpaceShipControl {
        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(){};
    }
    
    package chapter7reusing;
    
    public class SpaceShipDelegation {
        private String name;
        private SpaceShipControl control = new SpaceShipControl(); // 成员对象置于类中(就像组合)
    
        public SpaceShipDelegation(String name) {
            this.name = name;
        }
    
        //Delegated methods;
        public void back(int velocity) {
            control.back(velocity);
        }
    
        public void up(int velocity) {
            control.up(velocity);
        }
    
        public void down(int velocity) {
            control.down(velocity);
        }
    
        public void forward(int velocity) {
            control.forward(velocity);
        }
    
        public void left(int velocity) {
            control.left(velocity);
        }
    
        public void right(int velocity) {
            control.right(velocity);
        }
    
        public void turboBoost(int velocity) {
            control.turboBoost();
        }
    
        public static void main(String[] args) {
            SpaceShipDelegation protector = new SpaceShipDelegation("NSEA Protector");
            protector.forward(100);
        }
    }
    
    

    7.4结合使用组合和继承

    package chapter7reusing;
    
    class Plate {
        Plate(int i) {
            System.out.println("Plate constructor");
        }
    }
    
    class DinnetPlate extends Plate {
    
        DinnetPlate(int i) {
            super(i);
            System.out.println("DinnetPlate constructor");
        }
    }
    
    class Utensil { //器皿
        Utensil(int i) {
            System.out.println("Utensil constructor");
        }
    }
    
    class Spoon extends Utensil {
    
        Spoon(int i) {
            super(i);
            System.out.println("Spoon constructor");
        }
    }
    
    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");
        }
    }
    
    
    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 DinnetPlate dp;
    
        public PlaceSetting(int i) {
            super(i + 1);
            sp = new Spoon(i + 2);
            frk = new Fork(i + 3);
            kn = new Knife(i + 4);
            dp = new DinnetPlate(i + 5);
            System.out.println("PlaceSetting constructor");
        }
    
        public static void main(String[] args) {
            PlaceSetting x = new PlaceSetting(9);
        }
    }
    

    7.4.1 确保正确清理

    不建议使用finalize()

    package chapter7reusing;
    // 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");
        }
    
        void dispose() {
            System.out.println("Erasing Circle");
            super.dispose();
        }
    }
    
    class Triangle extends Shape {
        Triangle(int i) {
            super(i);
            System.out.println("Drawing Triangle");
        }
    
        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);
        }
    
        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(1);
            t = new Triangle(1);
            System.out.println("Combined constructor");
        }
    
        public void dispose() { //注意与初始化的顺序相反 防止子对象依赖另一个子对象
            System.out.println("CADSystem.dispose()");
            t.dispose();
            c.dispose();
            for (int i = lines.length - 1; i >= 0; i--)
                lines[i].dispose();
            super.dispose();
        }
    
        public static void main(String[] args) {
            CADSystem x = new CADSystem(47);
            try {
                // Code and exception handing……
            } finally {
                x.dispose();
            }
        }
    }
    

    7.4.2 名称屏蔽

    重载机制 在导出类或基类 都正常工作

    package chapter7reusing;
    
    class Homer {
        char doh(char c) {
            System.out.println("doh(char)");
            return 'd';
        }
    
        float doh(float f) {
            System.out.println("doh(float)");
            return 1.0f;
        }
    }
    
    class Milhouse {
    
    }
    
    class Bart extends Homer {
        void doh(Milhouse m) {
            System.out.println("doh(Milhouse)");
        }
    }
    
    public class Hide {
        public static void main(String[] args) {
            Bart b = new Bart();
            b.doh(1);
            b.doh('x');
            b.doh(1.0f);
            b.doh(new Milhouse());
        }
    }
    

    7.5 组合与继承之间选择

    package chapter7reusing;
    
    class Engine {
        public void start() {
        }
    
        public void rev() {
        }
    
        public void stop() {
        }
        public void service(){
            System.out.println("service");
        }
    }
    
    class Wheel {
        public void inflate(int psi) {
        } //inflate 充气
    }
    
    class Window {
        public void rollup() {
        }
    
        public void rolldown() {
        }
    }
    
    class Door {
        public Window window = new Window();
    
        public void open() {
        }
    
        public void close() {
        }
    }
    
    public class Car {
        public Engine engine = new Engine(); //特例,一般是private 有助于客户端程序员了解如何使用类
        public Wheel[] wheel = new Wheel[4];
        public Door
                left = new Door(),
                right = new Door();
    
        public Car() {
            for (int i = 0; i < 4; i++)
                wheel[i] = new Wheel();
        }
    
        public static void main(String[] args) {
            Car car = new Car();
            car.left.window.rollup();
            car.wheel[0].inflate(72);
            car.engine.service();
        }
    
    }
    

    7.6 protected 关键字

    protected 对于类用户而言,是private,但对于导出类,或包内的类来说,是可访问的。

    package chapter7reusing;
    
    // The protected keyword.
    class Villain {
        private String name;
    
        protected void set(String nm) {
            name = nm;
        }
    
        public Villain(String name) {
            this.name = name;
        }
    
        public String toString() {
            return "I'm a Villain and my name is " + name;
        }
    }
    
    public class Orc extends Villain {
        private int orcNumber;
    
        public Orc(String name, int orcNumber) {
            super(name);
            this.orcNumber = orcNumber;
        }
    
        public void change(String name, int orcNumber) {
            set(name); // Available because it's protected.
            this.orcNumber = orcNumber;
        }
    
        public String toString() {
            return "Orc" + orcNumber + ": " + super.toString();  // 根据基类版本
        }
    
        public static void main(String[] args) {
            Orc orc = new Orc("Limburger", 12);
            System.out.println(orc);
            orc.change("Bob", 19);
            System.out.println(orc);
        }
    
    }
    
    

    向上转型

    术语来源: 类继承图 绘制方法为基础
    导出类 是 基类的 一个超集,向上转型过程中,唯一可能 是丢失方法

    class Instrument {
        public void play() {
            System.out.println("Instrument  play()");
        }
    
        static void tune(Instrument i) {
            i.play();
        }
    }
    
    public class Wind extends Instrument {
        public static void main(String[] args) {
            Wind flute = new Wind();
            Instrument.tune(flute); // 将 Wind引用转换为Instruments 引用的动作: 向上转型
        }
    }
    

    再论组合与继承

    最可能:
    数据和方法包装一个类中,使用该类对象。
    组合技术 使用现有类,开发新类。
    继承技术不太常用。 必须向上转型,继承必要

    package chapter7reusing;
    
    class Amphibian {
        public void swim() {
            System.out.println("swim");
        }
    
        static void action(Amphibian am) {
            System.out.println("Amphibian: ");
            am.swim();
        }
    }
    
    public class Frog extends Amphibian {
     //   public void swim() {
      //      System.out.println("Frog");
        }
    
        public static void main(String[] args) {
            Frog frog = new Frog();
            Amphibian.action(frog); //使用基类的静态方法
        }
    }
    
    或者
    

    package chapter7reusing;

    class Amphibian {
    public void swim() {
    System.out.println("swim");
    }

    static void action(Amphibian am) {
        System.out.println("Amphibian: ");
        am.swim();
    }
    

    }

    public class Frog extends Amphibian {
    // public void swim() { //覆盖基类的定义,则调用导出类的方法
    // System.out.println("Frog");
    // }

    public static void main(String[] args) {
        Amphibian frog = new Frog(); //定义时 向上转型
        frog.action(frog);
    }
    

    }

    
    ## 7.8 final关键字
    设计  效率
    用到final 的几种情况:数据 方法 类
    final 在字段定义或者构造器中 初始化
    
    ### 7.8.1 final 数据
    1.永不改变的编译时常量  大写 下划线分隔单词
    2.运行时初始化的值,不希望它被改变
    
    ```java
    package chapter7reusing;
    
    import javax.swing.*;
    import java.util.Random;
    
    class Value {
        int i;
    
        public Value(int i) {
            this.i = i;
        }
    }
    
    public class FinalData {
        private static Random random = new Random(47);
        private String id;
    
        public FinalData(String id) {
            this.id = id;
        }
    
        // 编译时数值 final基本类型  编译期常量
        private final int valueOne = 9;
        private static final int VALUE_TWO = 99;
        // 典型 定义  public 可用于包之外 static 只有一份 final 常量
        public static final int VALUE_THREE = 39;
    
        // 非编译期常量 数据是final,但运行时随机生成数值初始化
        private final int i4 = random.nextInt(20);
        static final int INT_5 = random.nextInt(20);
    
        private Value v1 = new Value(11);
        private final Value v2 = new Value(22); // v2 不能指向另一个新对象
        private static final Value VAL_3 = new Value(33);
        // Arrays:
        private final int[] a = {1, 2, 3, 4, 5, 6};
        public String toString(){
            return id + ":" + "i4 = " + i4 + ", INT_5 = " +INT_5;
        }
    
        public static void main(String[] args) {
            FinalData fd1 = new FinalData("fd1");
    //        fd1.valueOne++; // final 变量
            fd1.v2.i++; // 对象不是常量
            fd1.v1 = new Value(9); //可以,不是final
            for(int i =0;i<fd1.a.length;i++)
                fd1.a[i]++; // 对象不是常量
    //        fd1.v2 = new Value(0); // can't
    //        fd1.VAL_3 = new Value(1); // can't
    //        fd1.a = new int[3];
            System.out.println(fd1);
            System.out.println("Creating new FinalData");
            FinalData fd2 = new FinalData("fd2");
            System.out.println(fd1);
            System.out.println(fd2);
    
        }
    
    }
    
    

    空白final
    声明为final 但未给定初值的字段

    package chapter7reusing;
    
    class Poppet {
        private int i;
    
        Poppet(int ii) {
            i = ii;
        }
    }
    
    public class BlankFinal {
        private final int i = 0; // 初始化 final
        private final int j; // 空白final
        private final Poppet p; // 空白引用 final
    
        // 空白final 必须在 构造方法中 初始化
        public BlankFinal() {
            j = 1;
            p = new Poppet(1);
        }
    
        public BlankFinal(int x) {
            j = x;
            p = new Poppet(x);
        }
    
        public static void main(String[] args) {
            new BlankFinal();
            new BlankFinal(47);
        }
    }
    
    
    

    final 参数

    无法在方法中更改参数引用所指向的对象

    package chapter7reusing;
    
    class Gizmo {
        public void spin() {
        }
    }
    
    public class FinalArguments {
        void with(final Gizmo g) {
    //        g = new Gizmo(); // g是 final
        }
    
        void without(Gizmo g) {
            g = new Gizmo();
            g.spin();
        }
    
        //    void f(final int i) { // 无法修改参数
    //        i++;
    //    }
        int g(final int i) { // 可以读参数
            return i + 1;
        }
    
        public static void main(String[] args) {
            FinalArguments bf = new FinalArguments();
            bf.without(null);
            bf.with(null);
        }
    }
    

    7.8.2 final 方法

    方法锁定,防止 继承类修改 不会被覆盖
    效率 不建议

    final 和private 关键字
    类中private方法 隐式 指定final

    方法为private , 就不是基类接口但一部分
    覆盖错觉:并没有覆盖,而是生成了一个新的方法

    package chapter7reusing;
    
    class WithFinals {
        private final void f() {
            System.out.println("WithFinals.f()");
        }
    
        private void g() {
            System.out.println("WithFinals.g()"); // 隐式 final
        }
    }
    
    class OverridingPrivate extends WithFinals {
        private final void f() {
            System.out.println("OverridingPrivate.f()");
        }
    
        private void g() {
            System.out.println("OverridingPrivate.g()");
        }
    }
    
    class OverridingPrivate2 extends OverridingPrivate {
        public final void f() {
            System.out.println("OverridingPrivate2.f()");
        }
    
        public void g() {
            System.out.println();
        }
    }
    
    public class FinalOverRidingIllusion {
        public static void main(String[] args) {
            OverridingPrivate2 op2 = new OverridingPrivate2();
            op2.f();
            op2.g();
            OverridingPrivate op = op2; // 向上转型 但不能调用方法
    //        op.f();
    //        op.g();
            WithFinals wf = op2;
    //        wf.f();
    //        wf.g();
        }
    }
    

    7.8.3 final 类

    final 类,禁止继承,所有方法隐式指定为final

    7.8.4 final 忠告

    关于Vector/ArrayList Hashtable/HashMap 关于 Final没看明白

    7.9 初始化 及 类的加载

    基类static 初始化 - 导出类 static 初始化 类加载完毕
    -创建对象
    基本类型初始化0 对象引用初始化null
    基类构造器 导出类构造器
    实例变量

    构造器 本质是 静态方法
    经典
    package chapter7reusing;
    
    class Insect {
        private int i = 9;
        protected int j;
    
        Insect() {
            System.out.println("i = " + j + ",j +" + j);
            j = 39;
        }
    
        private static int x1 = printInit("static Insect.x1 initialized");
    
        static int printInit(String s) {
            System.out.println(s);
            return 47;
        }
    }
    
    public class Beetle extends Insect {
        private int k = printInit("Beetle.k initialized");
    
        public Beetle() {
            System.out.println("k = " + k);
            System.out.println("j = " + j);
        }
    
        private static int x2 = printInit("static Beetle.x2 initialized");
    
        public static void main(String[] args) {
            System.out.println("Beetle Constructor");
            Beetle b = new Beetle();
        }
    }/* Output
    static Insect.x1 initialized
    static Beetle.x2 initialized
    Beetle Constructor
    i = 0,j +0
    Beetle.k initialized
    k = 47
    j = 39
    */
    
    class LoadTest {
        // The static clause is executed
        // upon class loading:
        static {
            System.out.println("Loading LoadTest");
        }
        static void staticMember() {}
    }
    public class E23_ClassLoading {
        public static void main(String[] args) {
            System.out.println("Calling static member");
            LoadTest.staticMember();
            System.out.println("Creating an object");
            new LoadTest();
        }
    } /* Output:
     Calling static member
     Loading LoadTest
     Creating an object
     *///:~
    
  • 相关阅读:
    Java序列化的机制和原理
    范型练习
    Java范型
    Hadoop之HelloWorld
    IEnumerable和IEnumerator
    浅谈静态变量和类
    MVC中的Startup.Auth.cs、BundleConfig.cs、FilterConfig.cs和RouteConfig.cs
    "ApplicationDbContext"(泛指之类的数据库上下文模型)上下文的模型已在数据库创建后发生更改。请考虑使用 Code First 迁移更新数据库。
    C#.NET的微信功能开发学习
    本地Fiddler传递XML格式数据,调试微信功能。
  • 原文地址:https://www.cnblogs.com/erinchen/p/11769005.html
Copyright © 2020-2023  润新知