Polymorphism in Java
Category Programming Techniques
Polymorphism is generally divided into two types: overriding polymorphism and overloading polymorphism.
-
Overloading Polymorphism, also known as compile-time polymorphism. This means that this type of polymorphism is determined at compile time. Overloading is well-known; a set of methods with the same name but different parameter lists is considered overloading. When calling an overloaded method, different results are obtained by passing different parameters.
>
However, there is ambiguity here. Some people believe that overloading should not be considered polymorphism. Many people's understanding of polymorphism is: the specific type that the reference variable defined in the program points to, and the method call made through this reference variable, are not determined during programming, but are determined at runtime. This situation is called polymorphism. This definition describes our second type of polymorphism—overriding polymorphism. Moreover, overloading polymorphism is not unique to object-oriented programming, while polymorphism is one of the three main features of object-oriented programming (if I'm wrong, please let me know...).
I don't think it's necessary to delve into these definitions. My understanding is: the ability of the same action to have multiple different manifestations or forms is polymorphism. Therefore, I believe that overloading is also a form of polymorphism. If you disagree with this view, I accept that.
-
Overriding Polymorphism, also known as runtime polymorphism. This type of polymorphism is implemented through dynamic binding technology, which means that the actual type of the referenced object is determined during execution, and the corresponding method is called based on its actual type. That is, only when the program runs, you know which subclass method is being called.
This polymorphism is achieved through method overriding and upcasting. The example in our code above is a complete case of overriding polymorphism. All the polymorphism we will discuss next is overriding polymorphism, as it is the true polymorphism in object-oriented programming.
Upcasting
Converting a subclass reference to a superclass type is called upcasting. Simply put, it is converting a subclass object to a superclass object. The superclass object here can be an interface.
Consider a well-known example:
Example
public class Animal {
public void eat(){
System.out.println("animal eatting...");
}
}
public class Cat extends Animal{
public void eat(){
System.out.println("我吃鱼");
}
}
public class Dog extends Animal{
public void eat(){
System.out.println("我吃骨头");
}
public void run(){
System.out.println("我会跑");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Cat(); // Upcasting
animal.eat();
animal = new Dog();
animal.eat();
}
}
// Result:
// 我吃鱼
// 我吃骨头
This is upcasting, Animal animal = new Cat();
converts the subclass object Cat to the superclass object Animal. At this time, the method called by the reference animal is the subclass method.
Issues to be aware of during casting
During upcasting, methods uniquely defined in the subclass will be lost. For example, the run method defined in the Dog class, when the animal reference points to a Dog class instance, the run method is inaccessible,
animal.run()
will report an error.A subclass reference cannot point to a superclass object.
Cat c = (Cat)new Animal()
is not allowed.
Benefits of upcasting
Reduces duplicate code, making the code cleaner.
Improves system extensibility.
Downcasting
The opposite of upcasting is downcasting. Downcasting is converting a superclass object to a subclass object. (Be careful! There are pitfalls here.)
Case-driven
Consider an example:
// Still using animal, cat, and dog
Animal a = new Cat();
Cat c = ((Cat) a);
c.eat();
// Output: 我吃鱼
Dog d = ((Dog) a);
d.eat();
// Error: java.lang.ClassCastException: com.chengfan.animal.Cat cannot be cast to com.chengfan.animal.Dog
Animal a1 = new Animal();
Cat c1 = ((Cat) a1);
c1.eat();
// Error: java.lang.ClassCastException: com.chengfan.animal.Animal cannot be cast to com.chengfan.animal.Cat
Why doesn't the first block of code report an error? You probably already know, because a is originally a Cat object, so it naturally can be downcast to Cat, and it naturally cannot be converted to Dog. Have you ever seen a dog suddenly turn into a cat?
And a1 is an Animal object, it also cannot be downcast to any subclass object. For example, when you are archaeology, you find a new creature, know it is an animal, but you cannot directly say, oh, it is a cat, or it is a dog.
Downcasting precautions
The prerequisite for downcasting is that the superclass object points to a subclass object (that is, before downcasting, it must first be upcasted)
Downcasting can only be cast to the class object itself (a cat cannot become a dog).
Consider a classic example:
Example
class A {
public String show(D obj) {
return ("A and D");
}
public String show(A obj) {
return ("A and A");
}
}
class B extends A{
public String show(B obj){
return ("B and B");
}
public String show(A obj){
return ("B and A");
}
}
class C extends B{
}
class D extends B{
}
public class Demo {
public static void main(String[] args) {
A a1 = new A();
A a2 = new B();
B b = new B();
C c = new C();
D d = new D();
System.out.println("1--" + 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));
}
}
// Result:
// 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
// Can you understand this result? Analyze it yourself first.
The first three, analyzed forcibly, can still be understood. But the fourth one, you might be confused. Why isn't it b and b?
Here we need to learn something new.
>
When a superclass object reference variable references a subclass object, the type of the referenced object determines which member method to call, and the reference variable type determines the callable methods. If the method is not overridden in the subclass, it will look for it in the superclass.
It may be a bit convoluted to read. Let's look at a simple example first:
Example
class X {
public void show(Y y){
System.out.println("x and y");
}
public void show(){
System.out.println("only x");
}
}
class Y extends X {
public void show(Y y){
System.out.println("y and y");
}
public void show(int i){
}
}
class main{
public static void main(String[] args) {
X x = new Y();
x.show(new Y());
x.show();
}
}
// Result
// y and y
// only x
Y inherits from X, overrides the show(Y y) method in X, but does not override the show() method.
At this time, the reference type is X, and x points to an object of type Y. At this time, the method to be called is determined by Y and will first look in Y. When executing x.show(new Y());
, this method is defined in Y, so the method in Y is executed;
But when executing x.show();
, some people might say, Y doesn't have this method! It seems to be looking for the method in the superclass, because it calls the method in X.
In fact, Y does have the show() method, which is inherited from X, but it is not overridden in Y, so it is not explicitly written in Y. It looks like it is calling the method in X, but in fact, it is still calling the method in Y.
>
At this point, it's not hard to understand the above difficult sentence, right? X is the reference variable type, which determines which methods can be called; show() and show(Y y) can be called, while show(int i) cannot be called. Y is the type of the referenced object, which determines which method to call: call the method of Y.
The above is a simple knowledge, which is not enough for us to understand that complex example. Let's look at another piece of knowledge:
>
The priority of method calls in the inheritance chain: this.show(O), super.show(O), this.show((super)O), super.show((super)O).
If you can understand this calling relationship, you have mastered polymorphism. Let's go back to that complex example:
The relationship of abcd is as follows: C/D —> B —> A
Let's analyze 4: a2.show(b)
First, a2 is a reference type of A, pointing to an object of type B. A determines the callable methods: show(D obj) and show(A obj).
a2.show(b)
==>this.show(b)
, where this refers to B.Then, look for show(B obj) in class B, found it, but it's useless because the show(B obj) method is not within the callable range,
this.show(O)
fails, enter the next level:super.show(O)
, super refers to A.Look for show(B obj) in A, failed, because this method is not defined. Enter the third level:
this.show((super)O)
, this refers to B.Look for show((A)O) in B, found it: show(A obj), choose to call this method.
Output: B and A
If you can understand this process and analyze other situations, you really have mastered it.
Let's look at 9: b.show(d)
- First, b is a reference object of type B, pointing to an object of type B. No upcasting is involved, only methods in the current class will be called.
Look for the method
show(D obj)
in class B. Now you can't say it's not found, right? Found it, call the method directly.Output A and D.
Summary
This article covers the main points as follows:
Polymorphism, in short, is the ability of the same action to have multiple different forms or manifestations.
Types of polymorphism: runtime polymorphism and compile-time polymorphism.
Prerequisites for runtime polymorphism: inheritance (implementation), overriding, and upcasting.
Upcasting and downcasting.
The priority of method invocation in the inheritance chain:
this.show(O)
,super.show(O)
,this.show((super)O)
,super.show((super)O)
.
>
Source article: http://www.cnblogs.com/kexianting/p/8689031.html
#
-
** huanyouren
* m13**[email protected]
During upcasting, if the subclass does not have certain methods of the superclass, the subclass will automatically inherit all methods of the superclass and can also override them.
In upcasting, if method A is invoked and both the superclass and subclass have this method with the same number, position, and type of parameters, the subclass's method A is called; if only the subclass has method A or invokes an overloaded method of the subclass, and the superclass does not have the corresponding overloaded method (same name but different parameters), an error will occur.
class Animal { public void run(){ System.out.println("Animal Run"); } public void bark(){ System.out.println("Animal Bark"); } } class Dog extends Animal{ public void run(){ System.out.println("Dog Run"); } public void sleep(){ System.out.println("Dog Sleep"); } } public class Test{ public static void main(String[] args){ Animal a = new Dog(); a.run(); // Both Animal and Dog have the run method, so the subclass's run method is used, printing "Dog Run" a.bark(); // The bark method is only in the Animal superclass, but the subclass Dog inherits it, so it prints "Animal Bark" a.sleep(); // The sleep method is not in the Animal superclass but only in the Dog subclass, so it will cause an error, but can be successfully printed after downcasting ((Dog)a).sleep(); // Casting from Animal back to Dog class, prints "Dog Sleep" } }
** huanyouren
* m13**[email protected]
** Click to share notes
-
-
-