The vast sea of millions, thank you for this second you see here. I hope mine can help you! ‘!

May you keep your love and go to the mountains and seas in the coming days!

Java Basics (Polymorphism)

polymorphism

Polymorphism refers to 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 will point to which class instance of the 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.

Definition of polymorphism and necessary conditions for its existence

Definition of polymorphism:

  • Polymorphism is the ability to have many different manifestations or forms of the same behavior.
  • Polymorphism is the same interface, using different instances to perform different operations.

For example, both cat and dog belong to animals. Animals have a common behavior of eating, and different animals eat very different food.

The catIt likes to eat fish!

As for the dogWell, it prefers to chew on bones!

So polymorphism is when it comes to the act of eating, every animal behaves differently for the act of eating.

Three necessary conditions for the existence of polymorphism

  1. Inheritance or implementation

    In polymorphism there must be subclasses and superclasses that have an inheritance or implementation relationship.

  2. Method rewriting

    A subclass redefines (overrides) certain methods in its parent class, and its methods are called when those methods are called.

  3. A base class reference points to a derived class object, that is, a parent class reference points to a subclass object

    Superclass type: Refers to the type of the superclass from which the subclass object inherits, or the type of the parent interface implemented.

Polymorphic format:

The parent type variable name =newSubclass type (); Variable name. Method name ();Copy the code

Polymorphic formats can fully reflect the same interface, using different instances and performing different operations.

Next we specific case experience experience!

The case of polymorphism

The first thing we need to know about polymorphism is:

When a method is called in polymorphic mode, the first check is made to see if the method exists in the parent class. If not, a compilation error occurs. If so, the subclass overridden method is executed. If the subclass does not override the method, the parent class’s method is called.

To sum up: compile to the left, run to the right.

First of all, we define a parent animal class, which has the behavior of eating!

Then define a cat and dog class to inherit the animal class, rewrite the eating behavior inside!

The specific code is as follows:

Define an animal parent:

package com.nz.pojo;

/** * Define a parent class --> animal class * all animals have a behavioral attribute of eating */
public class Animal {

    public void eat(a) {
        System.out.println("Animals they all eat!!"); }}Copy the code

Define a cat subclass:

package com.nz.pojo;

/** * defines the cat as inheriting from the animal class, * rewriting the eating behavior inside, because cats also have eating behavior, but cats like to eat cans */
public class Cat extends Animal{

    public void eat(a) {
        System.out.println("Kittens love canned fish!"); }}Copy the code

Define a puppy subclass:

package com.nz.pojo;

/** * Defines the dog class as inheriting from the animal class, * rewriting the eating behavior inside, because dogs also eat, but dogs like to chew bones */
public class Dog extends Animal{

    public void eat(a) {
        System.out.println("Puppies like to chew bones!"); }}Copy the code

Define test class, test polymorphic form:

package com.nz;

import com.nz.pojo.Animal;
import com.nz.pojo.Cat;
import com.nz.pojo.Dog;

/** * Tests the form of polymorphism */
public class Demo {
    public static void main(String[] args) {

        // Create cat objects in polymorphic form
        Animal animal = new Cat();
        // call Cat's eat
        animal.eat();

        // Create dog objects in polymorphic form
        Animal animal2 = new Dog();
        // Call Dog's eatanimal2.eat(); }}Copy the code

Results obtained:

Kittens love canned fish! Dogs love to chew bones!Copy the code

The general structure of the class:

You can see that we can use polymorphic properties to get a eating behavior of different animals!

The benefits of polymorphism

Improved the extensibility of the code, using the parent class type as the method form parameter, passing the subclass object to the method, method call.

Let’s see:

Stick with the aforementioned animals, cats, and dogs.

Define test classes:

package com.nz;

import com.nz.pojo.Animal;
import com.nz.pojo.Cat;
import com.nz.pojo.Dog;

/** * The benefits of testing polymorphism */
public class Demo2 {
    public static void main(String[] args) {
        // Create cat and dog objects
        Cat cat = new Cat();
        Dog dog = new Dog();

        / / call catEat
        catEat(cat);
        / / call dogEat
        dogEat(dog);

		/* The advantage of polymorphism: we can use animalEat(Animal A) instead of the above methods. And the performance is the same, so we can use animalEat to directly replace the eating method of different animals. * /
        animalEat(cat);
        animalEat(dog);
    }

    /* Define a few different methods and see what happens when you call them. * /
    public static void catEat (Cat cat){
        cat.eat();
    }

    public static void dogEat (Dog dog){
        dog.eat();
    }

    public static void animalEat (Animal animal){ animal.eat(); }}Copy the code

Execution Result:

Kittens love canned fish! Dogs love to chew bones! Kittens love canned fish! Dogs love to chew bones!Copy the code

As you can see, because of polymorphism, our animalEat() method passes in the Animal type argument, and it is the parent of our Cat and Dog classes, which receive subclass objects, so we can pass Cat and Dog objects to the animalEat() method.

So we can completely use animalEat() instead of catEat() and dogEat() to achieve the same effect! So that we can no longer write xxxEat() method to pass in the specified animal parameters, so that the implementation class automatic switch.

So the benefits of polymorphism are reflected in: it can make our program written more simple, and have good scalability.

The disadvantages of polymorphism

From the advantage of polymorphism above, we can see that we can use the arguments of the parent class instead of the arguments of a subclass, thus achieving the program extension!

But if there are methods that are unique to a subclass, then our polymorphic writing method won’t be able to access subclass-specific methods.

Let’s see.

The code is as follows:

Redefine the cat subclass:

package com.nz.pojo;

/** * defines the cat as inheriting from the animal class, * rewriting the eating behavior inside, because cats also have eating behavior, but cats like to eat cans */
public class Cat extends Animal{

    public void eat(a) {
        System.out.println("Kittens love canned fish!");
    }

    /** * added a new way for cats to play with balls () */
    public void playBall(a) {
        System.out.println("Kittens love small balls!"); }}Copy the code

Define test classes:

package com.nz;

import com.nz.pojo.Animal;
import com.nz.pojo.Cat;

/** * Test the drawbacks of polymorphism! * /
public class Demo3 {
    public static void main(String[] args) {
        Animal animal = new Cat();

        animal.eat();

        animal.playBall();// Animal does not have this method}}Copy the code

It can be seen that animals and cats have a common way to eat, but cats have a way to play with balls. For the animal object, there is no way for the animal to play with the ball, so its compilation fails!

So what’s the solution? See the next chapter!

Reference type conversion

1. What is a reference cast and why is it needed?

In the case of polymorphisms, we can see that we can’t directly access the cat ball-playing method when using the animal object. This is what we said before: compile to the left, run to the right.

When we call a method in polymorphic mode, we first check to see if the method exists in the parent class to the left. If not, we get a compilation error. This means that the parent class cannot call methods that are unique to subclasses. ,

So if you compile it wrong, let alone run it. This is one of the little annoyances of polymorphism, and we have to transition down if we want to call subclass-specific methods.

2. Upward transition (automatic transition)

For downward transition, let’s talk a little bit about upward transition.

Upward transition:

Polymorphism itself is the default upward conversion (automatic conversion) of a subclass to its parent. When a superclass reference refers to a subclass object, it is an upward transition.

For the relationship between parent and child classes, let’s look at the diagram:

A parent class is a wide range of types as opposed to a child class, Animal is an Animal class, it’s a parent class. And Cat is a Cat, a subclass.

So for the parent Animal, its scope is relatively large, it includes all animals, including cats and dogs.

So for small subclass types, we can automatically cast variables directly to the parent type.

Use format:

The parent type variable name =newSubclass type (); Animal = Animal = AnimalnewCat(); Animal Animal = Animal Animalnew Cat();   
Copy the code

It automatically helps us to make an invisible transition to the animal class, because animals themselves include cats.

3. Downcast (cast)

Upcasting is a process by which subclasses are automatically converted to superclasses, so let’s look at the definition of downcasting:

Downward transformation:

A cast down is a cast down from a parent class to a child class, which is mandatory. One way to convert a superclass object into a subclass object, using a cast, is to cast it downward.

Why does this have to impose a conversion process of its own?

For the relationship between parent and child classes, let’s look at the diagram:

For the cat, it is just one part of the animal class, while for the animal class, it has many other subcategories such as dog, cow, pig and so on.

So when an animal parent wants to cast down, it doesn’t know which subclass to point to because it’s not sure, so it has to do a forced cast itself.

Use format:

Subclass type variable name = (subclass type) parent variable name; Animal = Animal = Animalnew Cat();
Cat cat = (Cat) animal;
cat.playBall();// Now we can use the cat method
Copy the code

So for the disadvantages of polymorphisms, we can not use subclass-specific parameters, we can also use a downward cast method, so that the type is cast to a subclass object, and then call subclass-specific methods!

4. The problem of downward transformation

While we can use a downward transition that allows us to use methods unique to subclasses, we can run into a problem with the transition if we are not careful. Let’s look at the following code:

public class Test {
    public static void main(String[] args) {
        // Upward transition
        Animal a = new Cat();  
        a.eat();               // 调用的是 Cat 的 eat

        // Downward transition
        Dog d = (Dog)a;       
        d.watchHouse();        // Call Dog watchHouse}}Copy the code

This code compiles, but when it runs, a ClassCastException is reported. This is because, of course, when you create Cat objects, you can’t convert them to Dog objects at runtime.

5. Transformation anomalies

In the process of transformation, it is not careful to encounter such problems, see the following code:

Define additional unique dog walking methods within the dog class:

package com.nz.pojo; /** * Define the dog class to inherit from the animal class, * then rewrite the inside of the eating behavior, because dogs also eat behavior, */ public class Dog extends Animal{public void eat() {system.out.println (" Dog eats a bone! ") {public void eat() {system.out.println (" Dog eats a bone! ") ); } public void walk() {system.out.println (); ); }}Copy the code

Defining test classes

package com.nz;

import com.nz.pojo.Animal;
import com.nz.pojo.Cat;
import com.nz.pojo.Dog;

/** * Test the downward transition of polymorphisms */
public class Demo4 {
    public static void main(String[] args) {

        // The process of upward transformation
        Animal animal = new Cat();

        // Call the cat eating method
        animal.eat();

        // Downward transition
        Dog dog = (Dog) animal;

        dog.walk(); // Dog walk can pass, but an error will be reported}}Copy the code

Results obtained:

Kittens love canned fish! Exception in thread"main" java.lang.ClassCastException: com.nz.pojo.Cat cannot be cast to com.nz.pojo.Dog
	at com.nz.Demo4.main(Demo4.java:20)
Copy the code

As you can see, even though our code compiles, it still fails at runtime, throwing a ClassCastException type conversion exception.

In fact, we can see that when we created Cat on the top, we forced it to be cast to Dog on the bottom, so when the program runs, it will throw a cast exception!

So how can we avoid this kind of anomaly? See the next section for analysis!

6. Instanceof keyword

Java provides us with a keyword instanceof that helps us avoid ClassCastException type conversion exceptions.

So how do you do that?

Format:

The variable nameinstanceofThe data typeCopy the code

Explanation:

  • Returns true if the variable is of this data type or a subtype of it.
  • If the variable is not of the data type or a subtype of it, return false.

Code implementation:

package com.nz;

import com.nz.pojo.Animal;
import com.nz.pojo.Cat;
import com.nz.pojo.Dog;

/** * Use instanceof to resolve type conversion exceptions! * /
public class Demo5 {
    public static void main(String[] args) {

        // The process of upward transformation
        Animal animal = new Cat();

        // Call the cat eating method
        animal.eat();

        // Downward transition
        if (animal instanceof Cat){
            Cat cat = (Cat) animal;
            cat.playBall();        // Call Cat playBall
        } else if (animal instanceof Dog){
            Dog dog = (Dog) animal;
            dog.walk();       // 调用的是 Dog 的 walk}}}Copy the code

Results:

Kittens love canned fish! Kittens love small balls!Copy the code

As you can see, it helps us determine whether the type is of that type or a subclass before performing a cast. If so, we can force the cast.

conclusion

I believe that you all have a certain understanding of the knowledge and use of polymorphism in Java features, waiting for the next more Basic Java learning bar!

Here, the world is closed for today, good night! Although this article is over, I am still here, never finished. I will try to keep writing articles. The coming days are long, why fear the car yao ma slow!

Thank you all for seeing this! May you live up to your youth and have no regrets!

Note: If there are any mistakes and suggestions, please feel free to comment and leave a message! If this article is also helpful to you, I hope you can give me a focus to collect, thank you very much!