Thinking in Java notes (eighth polymorphic)

Source: Internet
Author: User
Tags export class

The eighth chapter Polymorphic

In object-oriented programming language, polymorphism is the third basic feature following abstraction and skill. polymorphism can not only improve the organization and readability of code, but also create extensible programs.

The role of polymorphism is to eliminate the coupling between types.

8.1 Further discussion upward transformation

The practice of referring an object's reference to its base class object is referred to as an upward transformation. But there are also problems with this. Look at the following example:
public enum Note {
Middle_c, C_sharp, B_flat;
}

class Instrument {    public void play(Note n) {        System.out.println("Instrument.play()");    }}class Wind extends Insrument {    public void play(Note n) {        System.out.println("wind.play() + " n);    }}public class Music {    public static void tune(Instrument i) {        i.play(Note.MIDDLE_C);    }    public static void main(String[] args) {        Wind flute = new Wind();        tune(flute);        }}output: wind.play() MIDDLE_C

The Music.tune () method accepts a instrument reference and also accepts any export from the instrument class. When a wind reference is accepted in the tune () method, it is automatically transformed, allowing it to do so, because the interface in instrument is in the wind. An upward transition from wind will reduce the interface, but not less than the instrument interface.

8.1.1 Forgetting Object types

If the tune () method accepts a wind reference directly as its own parameter, it is more intuitive on the surface, but each time a new instrument is added (that is, the instrument subclass), the corresponding tune method needs to be overloaded once. However, if you take advantage of polymorphism, it can be much easier to refer to instrument's multiple export class references as instrument references.

8.2 Connections

After running the above program, the exported class of incoming instrument is referenced to the tune method, it can also identify which export class it is, many people will wonder, how does the compiler know? In fact, the compiler simply does not know ....

8.2.1 Method Call Binding

Associating a method call with the same method body is called a binding. Bindings are divided into early binding and late binding.

    • Early binding: There is no way to select the default binding for the process.
    • Late binding: The runtime binds based on the type of the object. Also known as dynamic binding or runtime binding.

In addition to the static method and the final method in Java (the private method belongs to the final method), all other methods are late-bound.

8.2.2 Produce the right behavior

All methods in the

    java are polymorphic by dynamic binding, and we can write only the program code that deals with the base class, and the code can run correctly for all exported classes. For example:

Class Shape {public void Draw () {} public void Erase () {}}class Circle extends Shape {public void draw () {    System.out.println ("Circle.draw ()");    } public void Erase () {System.out.println ("circle.erase ()");    }}class Square extends Shape {public void Draw () {System.out.println ("Square.draw ()");    } public void Erase () {System.out.println ("square.erase ()");    }}class Triangle extends Shape {public void Draw () {System.out.println ("Triangle.draw ()");    } public void Erase () {System.out.println ("triangle.erase ()");    }}class Randomshapegenerator {private random Rand = new Random (47);            Public Shape Next () {switch (Rand.nextint (3)) {default:case 0:return new Circle ();            Case 1:return New Square ();        Case 2:return New Triangle (); }}}public class Test {public static void main (string[] args) {Randomshapegenerator RSG = New Randomshapegenerator ();        Shape[] s = new shape[9];        for (int i = 0; i < s.length; i++) {S[i] = Rsg.next ();    } for (Shape shp:s) Shp.draw (); }} Output: Triangle.draw () Triangle.draw () Square.draw () Triangle.draw () Square.draw () Triangle.draw () Square.draw () Triangle.draw () Circle.draw ()

In the above example, the upward transformation takes place in return, each time it returns a reference to circle, Square, and triangle three, but we get a generic shape reference through the next () method and then use dynamic binding to implement polymorphism.

8.2.3 Scalability

For the above two methods (draw and erase), any shape of the export class, covering the two interfaces, with dynamic binding, we are able to use it very well, regardless of how each export class is implemented.

8.2.4 defects: Overriding of private methods

For example:

public class PrivateOverride {    private void f() {        System.out.println("private f()");    }    public static void main(String[] args) {        Private Override po = new Deived();        po.f();     }}class Derived extends PrivateOverride {    public void f() {        System.out.println("public f()");    }   }

As above, we expect the result to be "public f ()", but the result is "private f ()", because private is the final class method, it cannot be overwritten, and it belongs to the pre-binding, not the dynamic binding, and therefore cannot implement dynamic binding.

8.2.5 defects: Domain and Static methods

Once the polymorphic mechanism is known, it may be assumed that all things can occur in a polymorphic manner, whereas only ordinary methods exhibit polymorphism. If you access a domain directly, it will not behave as polymorphic. For example:

class Super {    public int field = 0;    public int getField() {        return field;    }}class Sub extends Super {    public int field = 1;    public int getField() {        return field;    }    public int getSuperField() {        return super.field;    }}public class JavaTest{    public static void main(String[] args) {        Super sup = new Sub(); //向上转型        //这里在直接访问域的时候,并没有出现理想中的多态        System.out.println("sup.field: " + sup.field + "\nsup.getField: " + sup.getField() + "\n");        Sub sub = new Sub();        System.out.println("sub.field: " + sub.field + "\nsub.getField: " + sub.getField() + "\nsub.getSuperField():" + sub.getSuperField());    }}输出为:sup.field: 0sup.getField: 1sub.field: 1sub.getField: 1sub.getSuperField():0

When a sub object is transformed into a super reference, any domain access operations will be parsed by the compiler, because polymorphism takes the form of dynamic binding instead of relying on the compiler, so polymorphism cannot be completed.

In the example above, there are two fields in a sub object called field (Super.field and Sub.field), whereas the default field generated when referencing field in sub is not a Super version of field, The indicated Super.field must therefore be displayed.

8.3 Constructors and Polymorphic

Constructors are usually different from other methods, as are the cases when polymorphism is involved. Although the constructor is not polymorphic (the constructor is actually a static method, it is simply an implicit static declaration).

Call order of the 8.3.1 constructor

In the previous [study notes] ("http://blog.csdn.net/jing_unique_da/article/details/45530563"), the order of initialization was also mentioned, and the order of the calls was:

    1. Call the constructor of the base class. This step continues recursively until it is recursive to the root class, and starts initializing from the root wizard out of class.
    2. Initializes a method that invokes a member in declaration order.
    3. Invokes the principal of the exported class constructor.
Behavior of polymorphic methods within the 8.3.3 constructor

Now it's time to analyze what happens when you call a dynamic binding method inside a constructor that is constructing an object that is being constructed. For example:

class Super {    public int field;    public Super() {        System.out.println("Super() Before");    getField();        System.out.println("Super() after");    }    public int getField() {        System.out.println("Super() " + field);    return field;    }}class Sub extends Super {    public int field = 1;    public Sub(int i) {        field = i;        System.out.println("Sub() " + field);    }    public int getField() {        System.out.println("Sub() " + field);        return field;    }}public class JavaTest{    public static void main(String[] args) {        new Sub(5);    }}输出为:Super() BeforeSub() 0Super() afterSub() 5

The GetField () method here is overridden, but the GetField method called in the Super class's constructor is not super, but the method is overwritten, and the result is not 5, but 0. The reason is that the construction sequence described earlier is incomplete. The actual process of initialization is:

    1. Before anything else happens, initialize the storage space allocated to the object to binary 0.
    2. Recursively calls the constructor of the base class.
    3. Invokes the initialization method of a member in the order in which it is declared.
    4. Invokes the constructor principal of the exported class.
8.4 Covariant return type

In Java SE5, the covariant return type is added, that is, the overridden method in the exported class can return some type of export of the return type of the base class method, some of which are bypassed, directly on the example:

class Grain {    public String toString() {        return "Grain";    }}class Wheat extends Grain {    public String toString() {        return "Wheat";    }}class Mill {    Grain process() {        return new Grain();    }}class WheatMill extends Mill {    Wheat process() {        return new Wheat();    }}public class JavaTest{    public static void main(String[] args) {        Mill m = new Mill();        Grain g = m.process();        System.out.println(g);        m = new WheatMill();        g = m.process();        System.out.println(g);    }}结果:GrainWheat

Thinking in Java notes (eighth polymorphic)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.