Java programming ideas --- Chapter VII multiplexing class (on)

Chapter VII  multiplexing class (on)

  Code reuse is a Java one of the many compelling features, but want to be very revolutionary language, copy the code and it can only be changed is not enough, he must also be able to do more things.

 

7.1 combined syntax

 

  Until now we have used a combination of a number of counts, simply put an object reference to the new class, for example:

 

class WaterSource {

    private String s;

    WaterSource () {

        System.out.println("WaterSource()");

        s = "Constructed";

    }

 

    public String toString() {

        return s;

    }

}

 

public class SprinklerSystem {

    private String value1, value2, value3, value4;

    private WaterSource source = new WaterSource();

    private int i;

    private float f;

    public String toString() {

        return "value1 = " + value1 + " " +

                "value2 = " + value2 + " " +

                "value3 = " + value3 + " " +

                "value4 = " + value4 + "\n" +

                "i = " + i + " " + "f = " + f + " "+

                "source = " + source;

    } 

 

    Public  static  void main (String [] args) { 

        sprinkler sprinkler = new sprinkler (); 

        System. out .println (sprinkler systems); 

    } 

}

 

  The output is:

WaterSource()

value1 = zero value2 = zero VALUE3 = zero VALUE4 = zero

i = 0 f = 0.0 source = Constructed

 

  In the two class method defined above, there is a very special: toString () , each non-basic class object has a toString () method, when the compiler needs a String and you have only one object, then the method It will be called. In this expression:

  "Source =" + source;

  The compiler will know that you want to put a String object is the same WaterSource adding objects, since only one String object and another String adding objects, the compiler will call toString () , the source is converted into a String , then two String linked together and the result is passed to the System.out.println () , when you want to create the class with such behavior, only need to write a toString () method can be.

  The compiler is not simply creates a default object for each reference, if you want to initialize these references, can the following locations in the code of conduct:

1 , define the object's place

2 , the configuration in the class

3 , (lazy initialization) before use of these objects

4 , initialization Example

 

7.2 inheritance syntax

 

  Inheritance is all OOP language and the Java language an integral part when creating a class is always inherited, so unless a different class inherits from, or is implicitly from Object inherit. In the succession process, the need to declare the new class is similar to the old class, this statement is by braces on the left before the main body of the class, the base class name followed by the keyword extends realized, when doing so, it will automatically get the base All fields and methods in the class. E.g:

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{

    public void scrub() {

        append(" Detergent.scrub()");

        super.scrub();

    }

    public void foam() { append(" foam()"); }

 

    public static void main(String[] args) {

        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);

    }

}

 

The output is:

Cleanser dilute() apply() Detergent.scrub() scrub() foam()

Testing base class:

Cleanser dilute() apply() scrub()

 

  Cleanser and Detergent contain a main () method, which are disposed in each class a main () art methods may test each class unit becomes easy, and after the completion of the test unit and without delete main () , you can leave it to the next test.

Cleanser All methods must be public , in order to inherit, the general rule is that the amount of all the data members are designated as Private , all methods are designated as public , of course, in exceptional circumstances can make adjustments, but this method It is a very useful rule.

 

7.2.1 Initialization base class

 

  Now that the base class and derived classes involving two classes, so to try to imagine the results derived class objects generated. From the outside, he is a new class has the same interface as the base class, perhaps there will be some additional methods and fields, but not a copy of the base class inherits the interface, when the object of a derived class is created, the object contains a sub-object base class, you directly with the object created with the same base class subobject this time, the difference is that the latter from the outside, base subobject is packaged inside the object's derived class.

  Properly initialized for sub-objects of the base class is also important to call the base class constructor in the constructor to perform initialization, and the base class constructor has all the knowledge and ability to perform base classes required for the initialization, the Java will automatically exported class insert a call to the constructor base class constructor. E.g:

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();

    }

}

 

输出结果为:

Art constructor

Drawing constructor

Cartoon constructor

 

  我们发现,构件过程是从基类向外扩散的,所以基类在导出类构造器可以访问它之前,就已经完成了初始化,即使你不为Cartoon()创建构造器,编译器也会为你合成一个默认的构造器,这里的构造器是调用基类的构造器。

 

  带参数的构造器

 

  上面这些例子各个类都含有默认的构造器,即这些构造器都不带参数,编译器可以轻松调用他们是因为不必考虑传递什么样的参数问题,但是如果没有默认的基类构造器,或者想调用一个带参数的基类构造器,就必须使用关键字super显式编写调用基类构造器的语句,并且配以适当的参数列表:

class Game {

    Game(int i) {

        System.out.println("Game constructor");

    }

}

 

class BoardGame extends Game {

    BoardGame(int i) {

        super(i);

        System.out.println("Board constructor");

    }

}

 

public class Chess extends BoardGame{

    Chess() {

        super(1);

        System.out.println("Chess constructor");

    }

 

    public static void main(String[] args) {

        Chess x = new Chess();

    }

}

 

  输出结果如下:

Game constructor

Board constructor

Chess constructor

 

  如果不是在BoardGame()中调用了基类构造器,编译器将无法找到符合Game()形式的构造器,电泳基类构造器必须是你在导出类构造器中要做的第一件事。

 

7.3 代理

 

  第三种关系称为代理,Java没有提供对它的直接支持,这是继承于组合之间的中庸之道,我们将一个成员对象置于所要构造的类中,但与此同时我们在新类中暴露了该成员对象的所有方法。

 

7.4 组合使用组合和继承

 

  同时使用组合和继承是很常见的事,下面这个例子就同时使用了这两项技术,并配以必要的构造器初始化来创建更加复杂的类:

class Plate {

    Plate(int i) {

        System.out.println("Plate constructor");

    }

}

 

class DinnerPlate extends Plate {

    DinnerPlate(int i) {

        super(1);

        System.out.println("Dinner constructor");

    }

}

 

class Utensil {

    Utensil(int i) {

        System.out.println("Utensil constructor");

    }

}

 

class Spoon extends Utensil {

    Spoon(int i) {

        super(1);

        System.out.println("Spoon constuctor");

    }

}

 

class Fork extends Utensil {

    Fork(int i) {

        super(1);

        System.out.println("Fork constructor");

    }

}

 

class Knife extends Utensil {

    Knife(int i) {

        super(1);

        System.out.println("Knife constructor");

    }

}

 

class Custom {

    Custom(int i) {

        System.out.println("Custom constructor");

    }

}

 

public class PlaceSetting extends Custom{

    private Spoon spoon;

    private Fork fork;

    private Knife knife;

    private DinnerPlate dinnerPlate;

 

    public PlaceSetting(int i) {

        super(i + 1);

        spoon = new Spoon(i+2);

        fork = new Fork(i+3);

        knife = new Knife(i+4);

        dinnerPlate = new DinnerPlate(i+5);

        System.out.println("PlaceSetting constructor");

    }

 

    public static void main(String[] args){

        PlaceSetting x = new PlaceSetting(9);

    }

}

 

输出结果为:

Custom constructor

Utensil constructor

Spoon constuctor

Utensil constructor

Fork constructor

Utensil constructor

Knife constructor

Plate constructor

Dinner constructor

PlaceSetting constructor

 

7.4.1 确保正确清理

 

  Java中没有C++中析构函数的概念,析构函数是一种在对象被销毁时可以自动调用的函数,其原因可能是因为在Java中我们的习惯只是忘掉而不是销毁对象,并且让垃圾回收器在必要时释放其内存。

通常这样是好事,但有时类可能要在其生命周期内执行一些必须执行的清理活动,你可能并不知道垃圾回收器什么时候会被调用,因此我们想要清理一些东西就必须显式地编写一个特殊方法来做这件事。

 

7.4.2 名称屏蔽

 

  如果Java的基类拥有某个已经被多次重载的方法名称,那么在导出类中重新定义该方法名称并不会屏蔽其在基类中的任何版本,因此无论是在该层或者它的基类中对方法进行定义,重载机制都可以正常工作。

Java SE5新增加了@Override注解,它并不是关键字,但可以把它当成关键字使用,当你想要腹泻某个方法时,可以选择添加这个注解。

 

7.5 在组合与继承之间选择

 

  组合和继承都允许在新的类中放置子对象,组合是显式地这样做,而继承则是隐式地做。组合技术通常用于想在新类中使用现有类的功能而非它的接口这种情形,也就是在新类中嵌入某个对象,让其实现所需要的功能,但新类的用户看到的只是为新类所定义的接口,而非嵌入对象的接口。有时,允许类的用户直接访问新类中的组合成分是极具意义的,也就是说将对象声明为public,如果对象自身都隐藏了具体实现,那么这种做法是安全的。

  在继承的时候,使用某个现有类,并开发一个它的特殊版本,通常这意味着你在使用一个通用类,并为了某种特殊需要而将其特殊化。

 

 

Guess you like

Origin www.cnblogs.com/parable/p/11456047.html