Three major features of Java--polymorphism

Source: Internet
Author: User

Object-oriented programming has three main features: encapsulation, inheritance, polymorphism.

Encapsulation hides the internal implementation mechanism of the class, which can change the internal structure of the class without affecting the usage, and also protects the data. For the outside world its internal details are hidden and exposed to the outside world just by its access methods.

Inheritance is to reuse the parent class code. Two classes if there is a relationship between is-a can use inheritance, but also for the implementation of the multi-state of the foreshadowing. So what is polymorphism? What is the implementation mechanism of polymorphism?

The so-called polymorphism refers to the specific type of reference variable defined in the program and the method call issued by the reference variable is not determined during programming, but is determined during the program's run, that is, a reference to which the variable bottom will point to which class of the instance object, the reference variable emitted by the method call is the method implemented in the class, Must be determined by the time the program is running. Because when the program is run to determine the specific class, so that, without modifying the source code, you can bind the reference variable to a variety of different class implementations, resulting in the invocation of the specific method of the reference change, that is, do not modify the program code can be changed when the program runs the specific code, so that the program can select multiple running state, This is polymorphism.

Follow a principle: When a Superclass object reference variable refers to a subclass object, the type of the referenced object (that is, the specific type that the reference variable points to) rather than the type of the reference variable determines which member method to call, but the method that is called must be defined in the superclass, that is, the quilt class overrides the method. 1. If a is a reference to Class A, then a can point to an instance of Class A, or to a subclass of Class A.
2. If a is a reference to interface A, then a must point to an instance of a class that implements interface A.

For example, you are a wine God, have a unique feeling for wine. Some day home found a few cups inside are loaded with white wine, from the outside to see we can not know what this is what wine, only after drinking to be able to guess what kind of wine. You drink, this is Jiannanchun, drink again this is wuliangye, again drink this is alcoholic wine .... Here we can describe it as follows:

Wine A = Jiannanchun

Wine B = Wuliangye

Wine c = Alcoholic drink

...

What we are doing here is polymorphism. Jiannanchun, Wuliangye, alcoholic wine are the sub-class of wine, we just through the wine this one parent can refer to different subclasses, this is polymorphic-we can only run when we know the reference variable point to the specific instance object.

To understand polymorphism we have to understand what is "upward transformation". In the inheritance we briefly introduced the upward transformation, here is the wordy: in the above drinking example, wine (Win) is the parent class, Jiannanchun (JNC), Wuliangye (wly), alcoholic wine (JGJ) is a subclass. We define the following code:

JNC a = new JNC ();

For this code we are very easy to understand is to instantiate a Jiannanchun object! But what about this?

Wine a = new JNC ();

Here we understand that a wine type of a, which points to an Jnc object instance, is defined here. Since Jnc is inherited from wine, Jnc can automatically move up to wine, so a can point to Jnc instance objects. There is a great benefit in this, as we know in inheritance that subclasses are extensions of the parent class, that it can provide more powerful functionality than the parent class, and that if we define a reference type that refers to the parent class of a subclass, it can also use the subclass's powerful functionality in addition to referencing the generality of the parent class.

However, there are some drawbacks to the upward transformation, which is that it will inevitably lead to the loss of some methods and properties, which leads us not to acquire them. So a reference to a parent class type can call all the properties and methods defined in the parent class, and it is no more than a---1 for methods and properties that exist only with subclasses.

classWine { Public voidfun1 () {System.out.println ("The fun of Wine ...");    Fun2 (); } publi cvoid fun2 () {System.out.println ("The Fun2 of Wine ..."); }}classJNCextendsWine {/*** @desc Subclass overloads the parent class method does not exist in the parent class, and the parent class cannot refer to the method after it has been transformed .@paramA *@returnvoid*/     Public voidfun1 (String a) {System.out.println ("JNC Fun1 ...");    Fun2 (); }    /*** Subclasses overriding the parent class method to refer to the subclass of the parent class reference when calling Fun2, must be called the method*/     Public voidfun2 () {System.out.println ("JNC Fun2 ..."); }} Public classTest { Public Static voidMain (string[] args) {Wine a=NewJNC ();    A.fun1 (); }}
Output:wine's Fun ... JNC's Fun2 ...

From the running results of the program we find that A.fun1 () first runs the fun1 () in the parent class wine. Then run fun2 () in subclass Jnc.

Analysis: In this program the neutron class JNC overloaded the parent wine Method Fun1 (), Overrides Fun2 (), and the overloaded fun1 (String a) and fun1 () are not the same method, because there is no such method in the parent class, the method is lost after the upward transformation, So the wine type reference that executes JNC is not referenced by the FUN1 (String a) method. When the subclass Jnc overrides Fun2 (), the wine reference to JNC calls the Fun2 () method in Jnc. Fun2 () before actually hiding this, when a called FUN1 (), here is the equivalent of a, in fun1 () inside the fun2 () can be regarded as a.fun2 (), because A is a reference to the child class, the first call to find whether the subclass contains Fun2 method, If any, call Fun2 () in the subclass.

So for polymorphism we can summarize as follows:

A parent class reference to a subclass because it has been transformed upward, it can only access methods and properties that are owned in the parent class, and the reference is not available for methods that exist in the subclass and that do not exist in the parent class, although the method is overloaded. If subclasses override some of the methods in the parent class, they must be called using the methods defined in the subclass (dynamic joins, dynamic calls).

For object-oriented, polymorphism is divided into compile-time polymorphism and run-time polymorphism. Where compile-time polymorphism is static, mainly refers to the method of overloading, it is based on the parameter list to distinguish between different functions, by editing will become two different functions, at runtime is not polymorphic. While the runtime polymorphism is dynamic, it is implemented by dynamic binding, which is what we call polymorphism.

Multi-State implementationimplementation Conditions

In the beginning, it was mentioned that inheritance was prepared for polymorphic implementations. Subclass Child inherits the parent class father, we can write a reference to the parent class type of the child class, which can handle either the parent class Father object or the subclass child object, when the same message is sent to the child class or the parent class object. The object performs different behavior depending on the reference to which it belongs, which is polymorphic. That is, polymorphism is the same message that makes different classes respond differently.

There are three prerequisites for implementing polymorphism in Java: inheritance, rewriting, and upward transformation.

Inheritance: Subclasses and parent classes that have inheritance relationships must exist in polymorphism.

Rewrite: Subclasses redefine some methods in the parent class and call the methods of the subclasses when they are called.

Upward transformation: In polymorphic, a reference to a subclass needs to be assigned to the parent class object, so that the reference can have the ability to invoke methods and subclasses of the parent class.

Only by satisfying the above three conditions can we use uniform logic implementation code in the same inheritance structure to handle different objects, thus achieving different behavior.

For Java, its polymorphic implementation mechanism follows a principle: When a Superclass object references a variable that references a subclass object, the type of the referenced object rather than the type of the reference variable determines which member method to call, but the called method must be defined in the superclass, This means that the quilt class overrides the method (but if you force the superclass to be converted to subclasses, you can call a method that is newly added in the subclass and the superclass does not.) )。

implementation Form

There are two forms of polymorphism that can be implemented in Java. Inheritance and interfaces.

1. Polymorphism based on inheritance implementation

The implementation mechanism based on inheritance mainly manifests in the rewriting of some methods by the parent class and one or more subclasses inheriting the parent class, and the rewriting of the same method by many subclasses can show different behavior.

classWine {PrivateString name;  PublicString GetName () {returnname; }     Public voidsetName (String name) { This. Name =name; }     PublicWine () {} PublicString Drink () {return"The Drink is" +GetName (); }    /*** Rewrite ToString ()*/     PublicString toString () {return NULL; }} classJNCextendsWine { PublicJNC () {SetName ("JNC"); }    /*** Override the parent class method to implement Polymorphic*/     PublicString Drink () {return"The Drink is" +GetName (); }    /*** Rewrite ToString ()*/     PublicString toString () {return"Wine:" +GetName (); }}classJgjextendsWine { Publicjgj () {SetName ("Jgj"); }    /*** Override the parent class method to implement Polymorphic*/     PublicString Drink () {return"The Drink is" +GetName (); }    /*** Rewrite ToString ()*/     PublicString toString () {return"Wine:" +GetName (); }} Public classTest { Public Static voidMain (string[] args) {//defining an array of parent classesWine[] Wines =NewWine[2]; //define two subclassesJNC JNC =NewJNC (); Jgj jgj=Newjgj (); //Parent class referencing child class objectWines[0] =Jnc; wines[1] =jgj;  for(inti = 0; I < 2; i++) {System.out.println (wines[i].tostring ()+ "--" +Wines[i].drink ()); } System.out.println ("-------------------------------"); }}
output:wine:jnc--Drink is jncwine:jgj--drink is jgj

In the above code, JNC, jgj inherit wine, and rewrite the drink (), toString () method, the program run result is called the method in the subclass, output Jnc, jgj name, this is the performance of polymorphism. Different objects can perform the same behavior, but they all need to be implemented in their own way, thanks to an upward transformation.

We all know that all classes inherit from the superclass Object,tostring () method is also the method in object, when we write this:

Object o = new Jgj (); System.out.println (O.tostring ());

The result of the output is wine:jgj.

Object, Wine, jgj three inheritance chain relationship is: Jgj->wine->object. So we can say this: When a subclass overrides a method of the parent class is called, only the least-end method in the object's inheritance chain is called. But note that if you write this:

Object o = new Wine ();  System.out.println (O.tostring ());

The result of the output should be null, because JGJ does not exist in the inheritance chain of the object.

So the polymorphism based on inheritance can be summed up as follows: For a parent class type that references a subclass, when the reference is processed, it applies to all subclasses that inherit the parent class, the subclass object is different, the implementation of the method is different, and the behavior that occurs with the same action is different.

If the parent class is an abstract class, then the subclass must implement all the abstract methods in the parent class, so that all subclasses of the parent class must have a unified external interface, but the concrete implementations within it can vary. This allows us to use the uniform interface provided by the top-level class to handle the method at that level.

2. Multi-State based on interface implementation

Inheritance is manifested by overriding several different subclasses of the same method of the parent class, which can be realized by implementing the interface and overwriting several different classes of the same method in the interface.

In polymorphic interfaces, a reference to an interface must be an instance program that specifies a class that implements the interface, executing the corresponding method at run time, based on the actual type of the object reference.

Inheritance is a single inheritance and can only provide a consistent service interface for a set of related classes. But the interface can be multi-inheritance multi-implementation, it can use a set of related or irrelevant interfaces for combination and expansion, can provide a consistent service interface. So it has better flexibility than inheritance.

Classic Example
classA { PublicString Show (D obj) {return"A and D"; }     PublicString Show (A obj) {return"A and a"; }}classBextendsA { PublicString Show (B obj) {return"B and B"; }     PublicString Show (A obj) {return"B and A"; }}classCextendsB {}classDextendsB {} Public classTest { Public Static voidMain (string[] args) {A A1=NewA (); A A2=NewB (); b b=NewB (); C C=NewC (); D d=NewD (); System.out.println ("+"A1.show (b)); System.out.println ("2--" +A1.show (c)); System.out.println ("3--" +A1.show (d)); System.out.println ("4--" +A2.show (b)); System.out.println ("5--" +A2.show (c)); System.out.println ("6--" +A2.show (d)); System.out.println ("7--" +B.show (b)); System.out.println ("8--" +B.show (c)); System.out.println ("9--" +B.show (d)); }}
Output:    1--a and a    2--a and a    3--a and D    4--b and a    5--b and a    6--a and D    7--b and B    8 --b and B    9--a and D

Analytical:

Inheritance knot graph Relationships between references and objects

Method invocation Priority (an indeterminate argument, but the results of the analysis are OK):

This.show (o), Super.show (O), This.show ((Super) O), Super.show ((Super) O)

Call Results Analysis
A1.show (b) A.show (a A)->a and A A1 is a reference variable (type a) and the referenced object is a (type a). This is A1,b is an instance of B.
1.this.show (b b), does not exist, enter the second step.
2.super.show (b b), a does not exist in the parent class, enter the third step.
3.this.show (super) B obj, the parent class of B is a, equivalent to This.show (a), exists, so call show (a a) in a.
A1.show (c) A.show (a A)->a and A A1 is a reference variable (type a) and the referenced object is a (type a). This is A1,c is an instance of C.  1.this.show (c c), does not exist, enter the second step.  2.super.show (c c), a does not exist the parent class, enters the third step 3.this.show ((super) C obj), the C parent class is B, is equivalent to this.show (b b), does not exist. 4. Continue looking up for the parent class of B, This.show (super) B obj), the parent class of B is a, equivalent to This.show (a a), exists, so call show (a a) in a.
A1.show (d) A.show (d D)->a and D A1 is a reference variable (type a) and the referenced object is a (type a). This is A1,d is an instance of D. 1.this.show (d D), is present, so call show (d D) in a.
A2.show (b) B.show (a A)->b and A A2 is a reference variable (type a) and the referenced object is B (Type B). This is A2,b is an instance of B.  1.this.show (b b), does not exist, enter the second step.  2.super.show (b b), a does not exist in the parent class, enter the third step. 3.this.show (super) B obj, the parent class of B is a, is equivalent to This.show (a a), but at this point the referenced object is b,b overrides show (a a) in a, so call show (a a) in B.
A2.show (c) B.show (a A)->b and A A2 is a reference variable (type a) and the referenced object is B (Type B). This is A2,c is an instance of C.  1.this.show (c c), does not exist, enter the second step.  2.super.show (c c), a does not exist in the parent class, enter the third step.  3.this.show (super) C obj), the parent class of C is B, which is equivalent to this.show (b b), does not exist.  4. Continue looking up for the parent class of B, This.show (super) b obj, and B's parent Class A, equivalent to This.show (a a), exists. 5. Note that at this point the referenced object is B, and the call is on B (to find out if the referenced subclass overrides the method called in the parent class), B writes show (a a) for a, and therefore calls show (a a) in B.
A2.show (d) A.show (d D)->a and D A2 is a reference variable (type a) and the referenced object is B (Type B). This is A2,d is an instance of D.  1.this.show (d D), existence. 2. Check if this method has been rewritten in the referenced object, so call show (d D) in a.
B.show (b) B.show (b b)->b and B b is a reference variable (type B) and the referenced object is B (Type B). This is B,b is an instance of B. 1.this.show (b b), exists. The referenced object type is exactly the same as the reference variable type, so there is no override, so call show (b b) in B.
B.show (c) B.show (b b)->b and B b is a reference variable (type B) and the referenced object is B (Type B). This is B,c is an instance of C.  1.this.show (c c), does not exist, enter the second step.  2.super.show (c c), the parent class of B is a, which is equivalent to A.show (c c), does not exist, and enters three. 3.this.show (Super) C obj, the parent class of C is B, is equivalent to this.show (b b), exists, the referenced object type is exactly the same as the reference variable type, so there is no override, so call show (b b) in B.
B.show (d) A.show (d D)->a and D b is a reference variable (type B) and the referenced object is B (Type B). This is B,b is an instance of B.  1.this.show (d D), does not exist, enter the second step. 2.super.show (d D), the parent class of B is a, equivalent to A.show (d D), exists, so call show (d D) in Class A.

According to the above method, the other results can be obtained correctly.

The question goes on, now let's see how the above analysis process reflects the meaning of the words in the blue font. It says that when a superclass object references a variable that references a subclass object, the type of the referenced object rather than the type of the reference variable determines which member method to call, but the method that is called must be defined in the superclass, that is, the method covered by the quilt class. Take A2.show (b) for a while.

A2 is a reference variable, type A, which refers to an object of B, so the meaning of this sentence is B to decide which method to invoke. Therefore, the show (b obj) of B should be called to output "B and B". But why is it inconsistent with the results from the previous analysis?! The problem is that we don't overlook the second half of the blue font, which is particularly important: the method that is called must be defined in the superclass, that is, the method covered by the quilt class. Does the show (b obj) inside B have a definition in super Class A? No! That's not to mention being covered. In fact, this statement hides a message: it is still determined by the priority of the method invocation. It finds show (a obj) in Class A, and if subclass B does not overwrite the show (a obj) method, then it calls the show (a obj) of a (because B inherits a, although it does not overwrite this method, but inherits this method from superclass a, in a sense, The method that is called is determined by B, except that the method is implemented in A); now subclass B overrides Show (a obj), so it eventually locks to show (a obj) of B. This is what the meaning of the sentence is.

Three major features of Java--polymorphism

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.