Object-oriented programming has three major features: encapsulation, inheritance and polymorphism.
Encapsulation hides the internal implementation mechanism of a class, changes the internal structure of a class without affecting usage, and protects data. Its internal details are hidden from the outside world, only its access method is exposed.
Inheritance is used to reuse parent code. Inheritance can be used if two classes have an IS-A relationship. At the same time, inheritance also pave the way for the realization of polymorphism. So what is polymorphism? What is the implementation mechanism of polymorphism? Let me reveal one by one:
So-called polymorphism is refers to the procedures defined in the reference variable is pointing to the specific type and referenced by the variable from method calls are not sure when programming, but during the program is run to determine, that is, a reference variable STLL can point to which class instance object, the reference variable from method calls the method to realize exactly is which class, It must be decided during the running of the program. Because the program is running to identify a specific class, so, don’t need to modify the source code, can make reference variables bound to the different class implements, leading to the reference call specific methods change, namely do not modify the program code can change the program of the specific binding in the runtime code, let the program can select multiple running state, this is polymorphism.
Let’s say you’re a dionysian with a passion for wine. One day when I got home, I found several cups on the table filled with baijiu. From the outside, it was impossible for us to know what it was. Only after drinking it could we guess what kind of wine it was. Once you drink, this is Jiannanchun, then drink this is Wuliangye, then drink this is drunkard wine… Here we can describe it as follows:
Wine A = Jiannan Spring
Wine B = Wuliangye
Wine C = alcoholic wine
…
And what’s happening here is polymorphism. Jiannanchun, Wuliangye and Jiujiu are all subclasses of wine. We can refer to different subclasses of wine only through the parent class of wine. This is called polymorphism — we only know the specific instance object to which the reference variable refers when running.
Indeed, to understand polymorphism we must understand what upward transformation is. In the inheritance, we briefly introduced the upward transformation, here is the wordy part: In the above drinking example, wine (Win) is the parent class, while Jiannanchun (JNC), Wuliangye (WLY) and Drunkard wine (JGJ) are subclasses. We define the following code:
JNC a = new JNC();
For this code we are very easy to understand is nothing more than instantiate a jiannanchun object! But what about this?
Wine a = new JNC();
Here we understand that we define an A of type Wine that points to an instance of a JNC object. Since JNC is inherited from Wine, JNC can be automatically transformed upward to Wine, so A can point to JNC instance objects. There is a very big advantage to doing this. In inheritance we know that a subclass is an extension of its parent class, which can provide more power than the parent class. If we define a reference type that refers to the parent class, it can use the power of the subclass in addition to the generality of the parent class.
However, the downside of upward transformation is that it inevitably leads to the loss of methods and attributes that we cannot capture. So a reference to a superclass type can call all the attributes and methods defined in the superclass, except for methods and attributes that only exist in subclasses –1.
1 public class Wine {2 public void fun1(){3 system.out.println ("Wine Fun.....") ); 4 fun2(); 5} 6 6 public void fun2(){8 system.out.println (" fun2... ); 13 public class JNC extends Wine{13 /** 14 * @desc 13 public class JNC extends Wine{13 /** 14 * @desc 16 * @param a 17 * @return void 18 */ 19 public void fun1(String a){20 system.out.println ("JNC fun1... ); 21 fun2(); 26 * When fun2 refers to the parent class reference of the subclass, 27 */ 28 public void fun2(){29 system.out.println ("JNC fun2... ); 30 } 31 } 32 33 public class Test { 34 public static void main(String[] args) { 35 Wine a = new JNC(); 36 a.fun1(); 37}} 38 39 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40 Output: 41 Wine Fun... 42 JNC Fun2...Copy the code
A.fun1 () first runs fun1() in its parent Wine class. Then run fun2() from subclass JNC.
Analysis: In this program, the subclass JNC overloads the method fun1() of the parent class Wine and overwrites fun2(), and the overloaded fun1(String a) and fun1() are not the same method. Because there is no method in the parent class, the method will be lost after the upconversion. So a Wine type reference to JNC cannot reference the fun1(String a) method. The JNC subclass overrides fun2(), so a Wine reference to JNC calls the JNC fun2() method.
So we can sum up polymorphism as follows:
A parent reference to a subclass can only access methods and properties owned by the parent class because it has been upcast, and a reference to a method that exists in a subclass but does not exist in the parent class cannot be used, albeit by overloading the method. If a subclass overrides methods in its parent class, the methods defined in the subclass must be used when calling those methods (dynamic join, dynamic call).
For object orientation, polymorphism is divided into compile-time polymorphism and run-time polymorphism. Among them, when editing polymorphism is static, mainly refers to the method overload, it is according to the different parameter list to distinguish different functions, after editing will become two different functions, not polymorphic at run time. While runtime polymorphism is dynamic, it is achieved through dynamic binding, which we call polymorphism.
Implementation of polymorphism
2.1 Implementation Conditions
Inheritance was mentioned at the beginning in preparation for a polymorphic implementation. Subclass Child inherit the parent class Father, we can write a pointer to a subclass of the parent class type reference, this reference can handle both parent Father object, can also handle subclasses Child object, when the same message sent to subclass or superclass object, the object will be according to own reference and perform different actions, this is polymorphic. That is, polymorphism is when the same message causes different classes to respond differently.
There are three necessary conditions for Java to implement polymorphism: inheritance, rewriting, and upward transition.
Inheritance: In polymorphism, there must be a subclass and a parent class that have an inheritance relationship.
Override: A subclass redefines methods in its parent class that are called when those methods are called.
Upward transition: In polymorphism, a reference to a subclass is assigned to a superclass object so that the reference has the ability to call methods of the parent class and methods of the subclass.
Only when the above three conditions are met, can we use the same logical implementation code in the same inheritance structure to handle different objects, thus achieving different behavior.
For Java, for its part, the implementation of polymorphic mechanism follows a principle: when the superclass object reference variable subclass object reference and cited the type of object rather than a reference variable type determines the call who is a member of the method, but this is the method called must be defined in a superclass, method that is covered by a subclass.
2.2 Implementation Form
Polymorphism can be implemented in Java in two forms. Inheritance and interfaces.
2.2.1 Polymorphisms based on inheritance implementation
The implementation mechanism based on inheritance is mainly manifested in the rewriting of some methods by the parent class and one or more subclasses that inherit the parent class. Multiple subclasses can show different behaviors when rewriting the same method.
1 public class Wine { 2 private String name; 3 4 public String getName() { 5 return name; 6 } 7 8 public void setName(String name) { 9 this.name = name; 10} 11 12 public Wine(){13} 14 15 public String drink(){16 return "drink" + getName(); 21 */ 22 public String toString(){23 return null; 24 } 25 } 26 27 public class JNC extends Wine{ 28 public JNC(){ 29 setName("JNC"); 34 public String drink(){36 return "drink" + getName(); Public String toString(){43 return "Wine: "+ getName(); 44 } 45 } 46 47 public class JGJ extends Wine{ 48 public JGJ(){ 49 setName("JGJ"); 55 public String drink(){56 return "drink" + getName(); Public String toString(){63 return "Wine: "+ getName(); 67 public class Test {68 public static void main(String[] args) {69 Wine[] wines = new Wine[2]; // define two subclasses 72 JNC JNC = new JNC(); 73 JGJ jgj = new JGJ(); 74 75 // The parent class references the subclass object 76 wines[0] = JNC; 77 wines[1] = jgj; 78 79 for(int i = 0 ; i < 2 ; i++){ 80 System.out.println(wines[i].toString() + "--" + wines[i].drink()); 81 } 82 System.out.println("-------------------------------"); OUTPUT: 84}} 85 86 83 87 Wine: JNC - drinking JNC 88 Wine: JGJ - drinking JGJ 89 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --Copy the code
In the above code, JNC and JGJ inherit Wine and rewrite the drink() and toString() methods. The result of the program is to call the methods in the subclass and output the names of JNC and JGJ, which is the performance of polymorphism. Different objects can perform the same behavior, but they all need to perform it in their own implementation, thanks to the upward transition.
We know that all classes inherit from the superclass Object, and the toString() method is also an Object method when we write it like this:
Object o = new JGJ();
System.out.println(o.toString());
Copy the code
The output is Wine: JGJ.
The inheritance chain relation of Object, Wine and JGJ is: JGJ – >Wine – >Object. So we can say that when a subclass overrides a parent class, only the method at the end of the object’s inheritance chain is called. But notice if you write it like this:
Object o = new Wine();
System.out.println(o.toString());
Copy the code
The output should be Null because JGJ does not exist in the object inheritance chain.
So inheritance based polymorphisms can be summarized as follows: for a type of a parent class that refers to a subclass, when dealing with that reference, it applies to all subclasses that inherit from that parent class. Different subclass objects will implement different methods and perform different behaviors when performing the same action.
If the parent class is abstract, then the subclass must implement all the abstract methods in the parent class, so that all the subclasses of the parent class must have the same external interface, but their internal concrete implementation can be different. This allows us to use the uniform interface provided by the top-level class to handle methods at that level.
2.2.2 Polymorphisms based on interface implementation
Inheritance is represented by overriding several different subclasses of the same method in the parent class, and thus by implementing the interface and overriding several different classes of the same method in the interface.
In interface polymorphism, a reference to an interface must be an instance program that specifies a class that implements the interface and, at run time, executes the corresponding method according to the actual type of the object reference.
Inheritance is single inheritance and can only provide a consistent service interface for a set of related classes. But the interface can be multiple inheritance and multiple implementation, it can use a group of related or unrelated interface combination and expansion, can provide a consistent external service interface. So it has more flexibility than inheritance.
Three, classic examples.
Through the above, can be said to have a certain understanding of polymorphism. Now strike while the iron is hot. Look at an example. This example is a classic example of polymorphism
1 public class A { 2 public String show(D obj) { 3 return ("A and D"); 4 } 5 6 public String show(A obj) { 7 return ("A and A"); 8 } 9 10 } 11 12 public class B extends A{ 13 public String show(B obj){ 14 return ("B and B"); 15 } 16 17 public String show(A obj){ 18 return ("B and A"); 19 } 20 } 21 22 public class C extends B{ 23 24 } 25 26 public class D extends B{ 27 28 } 29 30 public class Test { 31 public static void main(String[] args) { 32 A a1 = new A(); 33 A a2 = new B(); 34 B b = new B(); 35 C c = new C(); 36 D d = new D(); 37 38 System.out.println("1--" + a1.show(b)); 39 System.out.println("2--" + a1.show(c)); 40 System.out.println("3--" + a1.show(d)); 41 System.out.println("4--" + a2.show(b)); 42 System.out.println("5--" + a2.show(c)); 43 System.out.println("6--" + a2.show(d)); 44 System.out.println("7--" + b.show(b)); 45 System.out.println("8--" + b.show(c)); 46 System.out.println("9--" + b.show(d)); 48 47}}Copy the code
Running results:
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
Copy the code
So if you look at the results 1, 2, and 3, it makes sense, but you start to get confused at 4, why isn’t the output “B and B” for 4?
When a superclass refers to a variable that refers to a subclass, the type of the referenced object, not the type of the referenced variable, determines whose member method is called, but the method being called must be defined in the superclass, that is, the method overridden by the subclass. That’s a generalization of polymorphism. Show (O), super.show(O), this.show((super)O), super.show((super)O).
Analysis:
From the above program, we can see that A, B, C, D have the following relationship.
5, a2. Show (c), a2 is A reference variable of type A, so this represents A, a2. Show (c), A superclass (super), A superclass (except Object), A superclass (super) This. Show ((super)O), C has A superclass B and A, so (super)O is B and A, this is also A, a2 is A reference to B, and B overwrites show(A obj). So the show(A obj) method of subclass B is eventually called, resulting in B and A.
I can confirm the other answers in the same way.
Methods have found there is a doubt but we here, let’s look at this sentence: when the superclass object reference variable reference subclass object, is the type of the reference object rather than a reference variable type whose members decided the call method, but this is the method called must be defined in a superclass, method that is covered by a subclass. Here’s an example of what this means: a2. Show (b);
Show (B) should call show(B obj) from B. The result should be “B and B”. But the method called here must be defined in the superclass. Show (B obj) exists in class A. It doesn’t exist! So that doesn’t apply here? So is this sentence wrong? Not too! It is still validated by the priority of the method called in the inheritance chain. That’s why it finds show(A obj) in class A, and because B overrides the method it calls the method in class B, otherwise it would call the method in class A.
Therefore, the principles followed by the polymorphic mechanism can be summarized as follows: When the superclass object reference variable subclass object reference and cited the type of object rather than a reference variable type determines the call who is a member of the method, but this is the method called must be defined in a superclass, that is covered by a subclass method, but it still according to the priority of a method call in the inheritance chain to confirm the method, the priority is: This. show(O), super.show(O), this.show((super)O), super.show((super)O).
Resources: blog.csdn.net/thinkGhoste… .
Baidu library: wenku.baidu.com/view/73f66f…