16_ The most comprehensive Java object-oriented explanation_ Encapsulation, inheritance and polymorphism

1, OOP feature 1: Encapsulation

Why package?

Before studying encapsulation, let's look at a piece of code:

class Book {
    String title;
    double price;

    public void getInfo() {
        System.out.println("Name of the book:" + title + " Price of books:" + price);
    }
}

public class BookTest {
    public static void main(String args[]) {
        Book book = new Book();
        book.title = "Java development";
        book.price = -89.9;
        book.getInfo();
    }
}

Operation results:

Name of book: price of Java development book: - 89.9

There is no syntax error in the above code, but there is a business logic error, because the price of books cannot be negative.

The user's direct operation on the attributes defined inside the class (member variables of the object) will lead to data error, confusion or security problems.

The reasons for this are:
After we create an object of a class, we can assign values to the attributes of the object by means of "object. Attribute". Here, the assignment operation is restricted by the data type and storage range of the attribute. In addition, there are no other constraints.
    
However, in practical problems, we often need to add additional constraints to attribute assignment. This condition cannot be reflected in the attribute declaration. We can only add constraints through methods. At the same time, we need to prevent users from assigning attributes in the way of "object. Attribute". You need to declare the attribute as private. At this time, encapsulation is reflected for the attribute.

We need to set the attribute in the Book class to be invisible to the outside world (which can only be accessed by this class). We can use the private keyword to define the attribute.

Embodiment of encapsulation

In Java, the data is declared as private, and then public methods are provided: getXxx() and setXxx() to operate the attribute, so as to achieve the following purposes:
Hide the implementation details of a class that do not need to be provided externally;
Users can only access data through pre-defined methods, and can easily add control logic to limit unreasonable operations on attributes;
Easy to modify and enhance the maintainability of the code;

1. Modify attribute visibility - > set to private

2. Create a public getter / setter method - > for reading and writing attributes

3. Add attribute control statement in getter / setter method - > judge the legitimacy of attribute value

Property privatization

class Book {
    String title;
    private double price;

    public void getInfo() {
        System.out.println("Name of the book:" + title + " Price of books:" + price);
    }
}

public class BookTest {
    public static void main(String args[]) {
        Book book = new Book();
        book.title = "Java development";
        book.price = -89.9;
        book.getInfo();
    }
}

Tips:

Error message:
        The field Book.price is not visible 
Operation error:
java: price is private access control in Book

Note: different tools have different prompts. But the general meaning is similar, which means that the field is invisible, that is, hidden.

We found that when accessing properties, external objects can no longer directly call the properties in the class. At this time, it is equivalent to that the properties of the Book class are invisible to the outside.

However, in order for the program to work properly, you must allow external users to manipulate the properties of the Book class. In Java development, there are such definitions for attributes. The attributes defined in the class require private declaration. If the attribute needs to be used externally, define the corresponding setter and getter methods of the attribute as required.

Provides methods for operating properties

Take the String price in the Book class as an example:

(1) the setter method is to set the property content:
                public void setPrice(double price)
Main: there are parameters.
(2) getter method is to obtain the attribute content:
                public double getPrice()
Note: no parameters.

Example: set the operation method for the encapsulation attribute.

class Book {

    String title;
    private double price;

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public void getInfo() {
        System.out.println("Name of the book:" + title + " Price of books:" + price);
    }
}

public class TestDemo {
    public static void main(String args[]) {
        Book book = new Book();
        book.title = "Java development";
        book.setPrice(-89.9);
        book.getInfo();
    }
}

Operation results:

Name of book: price of Java development book: - 89.9

It is found that the price of the book is negative, and the code for checking business logic errors needs to be added. You can add verification in the setter. If the value is positive, assign a value, otherwise it is the default value of 0.0:

public void setPrice(double price) {
    if (price < 0) {
        System.out.println("Wrong number of price!");
        return;
    }
    this.price = price;
}

For data validation, it should be done by auxiliary code in Java standard development. In actual development, setter s often simply set the property content, and getter s simply get the property content.

Development suggestion: when defining classes in the future, all attributes should be encapsulated in private. If the encapsulated attributes need to be operated externally, setter s and getter s should be written.
The above operations are actually part of the encapsulation.
        
Embodiment of packaging:
1. Encapsulation of attributes.
2. Private methods without external exposure.
3. Encapsulation of constructor. (singleton mode)
Etc

Example combination exception:

public class Human {
    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) throws Exception {
        // Encapsulate the validation logic of the age, rather than expose it to each caller
        if (age > 120 || age < 0) {
            throw new Exception("Invalid value of age");
        }
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Benefits of encapsulation

1. Data can only be accessed through specified methods
        
2. Implementation details of hidden data
        
3. It is convenient to modify and realize
        
4. It is convenient to add control statements
        
5. You can modify the read (getter) and write (setter) permissions of attributes
If only getter s are provided, it means read-only;
If only setter is provided, it means write only; (usually few)

Package summary

Encapsulation, also known as hiding the implementation, only exposes the external interface of the code unit and hides its specific implementation.

For example, mobile phones, keyboard, screen and earpiece of mobile phones are their external interfaces. You only need to know how to press keys to use the phone, without understanding how the internal circuit of the phone works. For another example, if I want to use the washing machine, I just need to press the switch and washing mode. Is it necessary to understand the internal structure of the washing machine? Is it necessary to touch the motor? Like mobile phones and washing machines, the encapsulation mechanism only exposes the external interface without requiring users to understand its internal implementation.     

The idea of encapsulation ensures the integrity of the internal data structure of the class, so that users can not easily and directly operate the internal data of the class, which reduces the impact on the internal data and improves the security and maintainability of the program.
    
Encapsulation is to hide the internal complexity of objects and only expose simple interfaces. It is convenient for external calls, so as to improve the scalability and maintainability of the system. Generally speaking, hide what should be hidden and expose what should be exposed. This is the design idea of encapsulation.

Our programming pursues "high cohesion and low coupling".
High cohesion: the internal data operation details of the class are completed by themselves, and external interference is not allowed;
Low coupling: only a small amount of external exposure is used.

There are many methods in jdk common classes, some of which are hidden and not used directly by external programs. They can only be called in class methods, and the exposed ones are exposed.

2, OOP feature 2: Inheritance

Why use inheritance?

To describe and process Student information, define the class Student:

public class Student {
    public String name;
    public int age;
    public Date birthDate;
    public String school;

    public String getInfo() {
        return "name: " + name + ",Age: " + age + ",date of birth: " + birthDate;
    }

    public void sleep() {
        System.out.println("Sleeping behavior");
    }

    public void study() {
        System.out.println("Learning behavior");
    }
}

To describe and process employee information, define the class Employee:

public class Employee {
    public String name;
    public int age;
    public Date birthDate;
    public String company;

    public String getInfo() {
        return "name: " + name + ",Age: " + age + ",date of birth: " + birthDate;
    }

    public void sleep() {
        System.out.println("Sleeping behavior");
    }

    public void work() {
        System.out.println("Work behavior");
    }
}

To describe and process Chef information, define the class Chef:

public class Chef {
    public String name;
    public int age;
    public Date birthDate;
    public String grade;

    public String getInfo() {
        return "name: " + name + ",Age: " + age + ",date of birth: " + birthDate;
    }

    public void sleep() {
        System.out.println("Sleeping behavior");
    }

    public void cooking() {
        System.out.println("Cooking behavior");
    }
}

We will find that the above three classes have the same behavior and characteristics. They all have name, age, birthDate attributes and gettInfo and sleep methods. There are many similar abstract entities, such as Teacher class, Customer class, Waiter class, etc; If we all follow the current writing method, it is equivalent to defining the same attributes and behaviors in N classes, and the reuse rate of this code is too low;

To solve this problem, we should find ways to improve the reusability of code.
    
How to do it?
When the same attributes and behaviors exist in multiple classes, these contents are extracted into a single class, so multiple classes do not need to define these attributes and behaviors, just inherit that class.
    
Multiple classes here are called subclasses (derived classes), and a single class is called a parent class (base class or superclass). It can be understood as: "subclass is a parent class".

Benefits / effects of inheritance:
Inheritance is to improve code reusability and reduce code redundancy;
Facilitate the expansion of functions;
It provides a premise for the use of polymorphism.

Note: don't inherit just to get a function in other classes.

What is inheritance?

Create a new class according to the type of an existing class without changing the form of the existing class. Adopt the form of the existing class and add new code to it. This method is called inheritance. Inheritance makes the subclass inherit the characteristics and behavior of the parent class, so that the subclass object (instance) has the instance domain and method of the parent class. That is, the subclass and the parent are "similar".

Here is an example of inheritance:

As shown in the figure above, animals inherit biological classes; Tigers inherit animals. From this example, it is obvious that the higher the class is, the more abstract it is, and the lower the class is, the more concrete it is. When we design, the parent class is often a more abstract class.

Inheritance is a cornerstone of Java object-oriented programming technology because it allows the creation of hierarchical classes.

Inheritance is that a subclass inherits the characteristics and behavior of the parent class, so that the subclass object (instance) has the member variables and methods of the parent class, or the class inherits methods from the parent class, so that the subclass has the same behavior as the parent class.
    
Inheritance is an indispensable part of all OOP and java languages. When a class is created, it is always inherited. Therefore, unless it is explicitly indicated to inherit from other classes, it is implicitly inherited from Java's standard root class Object

Embodiment of inheritance

The keyword extends indicates that the new class being constructed derives from an existing class.

The existing class is called super class, base class or parent class;
    
The new class is called a subclass, derived class, or child class.

Class inheritance syntax rules:
                class Subclass extends SuperClass{ }

Embodiment of inheritance:
1. Once the subclass inherits the parent class, all the properties and methods declared in the parent class are obtained in the subclass.
In particular, for a property or method declared private in the parent class, after the child class inherits the parent class, it is still considered to have obtained the private structure in the parent class.
2. After inheriting the parent class, a subclass can also declare its own unique properties or methods: to realize the expansion of functions, which we call subclass expansion.
In Java, the inherited keyword uses "extends", that is, the subclass is not a subset of the parent class, but an "extension" of the parent class.
The relationship between subclasses and superclasses is different from that between subsets and collections.

Write parent class: extract common attributes and methods

public class Person {
    public String name;
    public int age;
    public Date birthDate;

    public String getInfo() {
        return "name: " + name + ",Age: " + age + ",date of birth: " + birthDate;
    }

    public void sleep() {
        System.out.println("Sleeping behavior");
    }
}

Authoring subclasses: inheriting the parent class

Use the extends keyword to let the subclass inherit from the parent class, then the subclass has the properties and methods defined by the parent class, and there is no need to define them repeatedly;

Subclass example code:

public class Student extends Person{
    public String school;

    public void study() {
        System.out.println("Learning behavior");
    }
}

public class Employee extends Person{
    public String company;

    public void work() {
        System.out.println("Work behavior");
    }
}

public class Chef extends Person{
    public String grade;

    public void cooking() {
        System.out.println("Cooking behavior");
    }
}

Test class example code:

public class ExtendsTest {
    public static void main(String[] args) {
        Student student = new Student();

        // The Student class does not define these three properties, but because it inherits the Person class, it has the properties defined by the Person class
        student.name = "Zhang San";
        student.age = 22;
        student.birthDate = new Date(1992, 12, 22);

        // The school attribute is defined in the Student class. We can call it an extension of a subclass
        student.school = "Peking University";

        // The Student class does not define these two, but because it inherits the Person class, it has the methods defined by the Person class
        student.getInfo();
        student.sleep();

        // study() is defined in the Student class. We can also call it an extension of a subclass
        student.study();

        // Other similar
    }
}

Understanding private inheritance

Some books show that "subclasses can only inherit the non private properties and methods of the parent class", but this is not the case. In fact, "Java subclasses can inherit all the properties and methods of the parent class", but subclasses cannot call the private methods of the parent class for private reasons.

//Parent class
public class Father {

    private String name = "Zhang San";//Private property
    private String sex = "male";

    public void tell() {
        System.out.println("full name:" + name);
        System.out.println("Gender:" + sex);
    }

    private void speak() {
        System.out.println(name + "is speaking!");
    }

    private void sleep(){
        System.out.println("sleep...");
    }

    public void eat(){
        System.out.println("eat...");
        sleep();
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

//Subclass
public class Child extends Father {

}

//Test class
public class TestJava {

    public static void main(String[] args) {

        Child c = new Child();
        c.tell();// The tell method can be used
        // c.speak();// An error is reported. The private method of the parent class is not visible

        c.eat();
    }

}

You can see that the tell method is still available in the test class even if the attribute of the Child class object is not assigned. If the Child class does not inherit the private properties of the parent class, the tell method should report an error. The conclusion is that the subclass inherits everything from the parent class, and the modifier only affects whether the attribute or method is visible.

Explanation of the official Java document: a subclass cannot inherit the private properties of the parent class, but if the public methods in the subclass affect the private properties of the parent class, the private properties can be used by the subclass.

Understanding: subclasses cannot directly access private member variables and methods in the parent class.

Inherited rules

Java only supports single inheritance and multi-layer inheritance, and multiple inheritance is not allowed.

1. A class can be inherited by multiple subclasses.
2. Single inheritance of classes in Java: a class can only have one parent (direct parent).

3. Child parent class is a relative concept.
4. The parent class directly inherited by the child class is called direct parent class. The parent class of indirect inheritance is called indirect parent class.
5. After the subclass inherits the parent class, it obtains the properties and methods declared in the direct parent class and all indirect parent classes.

Inheritance summary

Inheritance is that a subclass inherits the characteristics and behavior of the parent class, so that the subclass object (instance) has the instance domain and method of the parent class. On this basis, new methods and member variables can be added to meet the requirements.
    
Inheritance needs to conform to the following relationships: is-a, the parent class is more general, and the child class is more specific.

Java only supports single inheritance and multi-layer inheritance, and multiple inheritance is not allowed.

Inheritance is to improve code reusability, reduce code redundancy, facilitate function expansion, and provide a premise for the use of polymorphism.
    
Code reuse is one thing. The most important thing is the so-called upward transformation, that is, the reference variable of the parent class can point to the child class object, which is the basis of the most important feature of Java object-oriented polymorphism.

Parent class members that cannot be inherited: constructors and constructors cannot be inherited, but subclasses can call the constructor of the parent class through super()

Advantages and disadvantages of inheritance

In object-oriented languages, inheritance is an essential and excellent language mechanism. It has the following advantages:
Code sharing reduces the workload of creating classes, and each subclass has the methods and properties of the parent class;
Improve code reusability;
A subclass can be similar to the parent, but different from the parent; (if you have the commonness of the parent class, you can also have your own characteristics);
Improve the scalability of the code, and the methods that implement the parent class can "do whatever they want". (override of method)
Improve the openness of products or projects.

All things in nature have both advantages and disadvantages, and the inherited disadvantages are as follows:
Inheritance is invasive. As long as you inherit, you must have all the properties and methods of the parent class;
Reduce code flexibility. Subclasses must have the properties and methods of the parent class, so that there are more constraints in the free world of subclasses;
Enhanced coupling. When the constants, variables and methods of the parent class are modified, the modification of the child class needs to be considered, and in the absence of specifications, this modification may lead to very bad results - large pieces of code need to be refactored.

3, OOP feature 3: polymorphism

What is polymorphism

From the literal meaning: it can be understood as a variety of forms of a thing. How to call a variety of forms of a thing?

Look at code analysis:

public class Person {
	String name;
	int age;
	
	int id = 1111;
	
	public void eat(){
		System.out.println("Man: eat");
	}
	
	public void walk(){
		System.out.println("Man: walk");
	}
	
}

public class Man extends Person{

    boolean isSmoking;

    int id = 2222;

    public void earnMoney(){
        System.out.println("Men are responsible for making money to support their families");
    }

    public void eat(){
        System.out.println("Men eat more meat and grow muscles");
    }

    public void walk(){
        System.out.println("Man's domineering walk");
    }

}

public class Woman extends Person{

    boolean isBeauty;

    public void goShopping(){
        System.out.println("Women like shopping");
    }

    public void eat(){
        System.out.println("Women eat less in order to lose weight");
    }

    public void walk(){
        System.out.println("Women walk gracefully");
    }
}

public class PersonTest {

    public static void main(String[] args) {

        Person p1 = new Person();
        p1.eat();

        Man man = new Man();
        man.eat();
        man.age = 25;
        man.earnMoney();

        System.out.println("---------------------------");

        // Object polymorphism: the reference of the parent class points to the object of the child class
        Person p2 = new Man();
        Person p3 = new Woman();
    }
}


A human being can be either a man object or a woman object; This is the polymorphism of objects.
    
Polymorphism is the most important concept in object-oriented, which is embodied in Java:
Object polymorphism: the reference of the parent class points to the object of the child class;  
    
Note: it can be directly applied to abstract classes and interfaces.

Use of polymorphism

	Encapsulation hides the internal implementation mechanism of the class, which can change the internal structure of the class without affecting the use, and also protect the data. To the outside world, its internal details are hidden, and only its access methods are exposed to the outside world.

	Inheritance is to reuse the parent code. If two classes exist IS-A Relationships can use inheritance. At the same time, inheritance also paves the way for the realization of polymorphism.

	So what is polymorphism? What is the implementation mechanism of polymorphism?

	The so-called polymorphism refers to the specific type pointed to by the reference variable defined in the program and the method call issued through the reference variable. It is not determined during programming, but only during the running of the program, that is, a reference variable will point to the instance object of which class, and the method call issued by the reference variable is the method implemented in which class, It can only be determined during the running of the program.
	
	Because the specific class is determined only when the program is running, the reference variable can be bound to various class implementations without modifying the source program code, resulting in the change of the specific method called by the reference, that is, the specific code bound when the program is running can be changed without modifying the program code, so that the program can select multiple running states, This is polymorphism.

	Java Reference variables have two types: compile time type and runtime type. The compile time type is determined by the type used when declaring the variable, and the runtime type is determined by the object actually assigned to the variable. Abbreviation: when compiling, look at the left; When running, look to the right.
		If compile time type and run-time type are inconsistent, object polymorphism occurs(Polymorphism)
		In the case of polymorphism, "look at the left": look at the reference of the parent class (the parent class does not have the methods specific to the child class)
		In the case of polymorphism, "look at the right": you are looking at the objects of the subclass (actually running the method of overriding the parent class by the subclass)

	If a reference type variable is declared as the type of the parent class, but actually refers to the subclass object, the variable can no longer access the properties and methods added in the subclass.
        Example code:
            Student m = new Student();
            m.school = "pku"; // Legal. The Student class has a school member variable
            Person e = new Student(); 
            e.school = "pku"; // Illegal. The Person class does not have a school member variable
            Property is determined at compile time e by Person Type, no school Member variable, so compilation error.

	Prerequisites for polymorphism:
		① Class inheritance  ② Method rewriting

	The polymorphism of objects is only applicable to methods, not attributes (see the left for compilation and operation)
public class PersonTest {

    public static void main(String[] args) {
        // Object polymorphism: the reference of the parent class points to the object of the child class
        Person p = new Man();

        // Use of polymorphism: when calling a method with the same name and parameters as the child parent class, the actual implementation is the virtual method call, which is the method of the child class overriding the parent class
        p.eat();
        p.walk();
		
        // Compilation error
        // p2.earnMoney();
        
        System.out.println(p.id);// 1111
    }
}

Polymorphism of objects - in Java, objects of subclasses can be used instead of objects of parent classes.
A variable can only have one definite data type.
A reference type variable may point to (Reference) many different types of objects.

Example code:
                Person p = new Student();
                Object o = new Person();// Variable o of type object, pointing to object of type person
                o = new Student(); // Object type variable o, pointing to student type object

The subclass can be regarded as a special parent class, so the reference of the parent type can point to the object of the subclass: upcasting.

Therefore, we can summarize polymorphism as follows:

Due to the upward transformation, the parent class reference pointing to the subclass can only access the methods and properties owned by the parent class. For the methods existing in the subclass but not in the parent class, the reference cannot be used, although the method is overloaded. If the subclass overrides some methods in the parent class, these methods defined in the subclass must be used when calling these methods (dynamic connection and dynamic call).

For object-oriented, polymorphism is divided into compile time polymorphism and run-time polymorphism. The compile time polymorphism is static, which mainly refers to the overloading of methods. It distinguishes different functions according to different parameter lists. After compilation, it will become two different functions, so it is not polymorphic at run time. The runtime polymorphism is dynamic, which is realized by dynamic binding, that is, what we call polymorphism.

Is polymorphism a compile time behavior or a run-time behavior?

//The certificate is as follows:
class Animal  {

    protected void eat() {
        System.out.println("animal eat food");
    }
}

class Cat  extends Animal  {

    protected void eat() {
        System.out.println("cat eat fish");
    }
}

class Dog  extends Animal  {

    public void eat() {
        System.out.println("Dog eat bone");
    }

}

class Sheep  extends Animal  {
    public void eat() {
        System.out.println("Sheep eat grass");

    }

}

public class InterviewTest {

    public static Animal  getInstance(int key) {
        switch (key) {
            case 0:
                return new Cat ();
            case 1:
                return new Dog ();
            default:
                return new Sheep ();
        }

    }

    public static void main(String[] args) {
        int key = new Random().nextInt(3);

        System.out.println(key);

        Animal  animal = getInstance(key);

        animal.eat();

    }

}

Understanding virtual method calls:

Normal method calls:
        Person e = new Person();
        e.getInfo();
        Student e = new Student();
        e.getInfo();

Virtual method call (polymorphic):
A method with the same name and parameters as the parent class is defined in the subclass. In the case of polymorphism, the method of the parent class at this time is called a virtual method. The parent class dynamically calls the method belonging to the subclass according to the different subclass objects assigned to it. Such method calls cannot be determined at compile time.
                Person e = new Student();
                e.getInfo(); // Call the getinfo () method of the Student class

Compile time type and runtime type
At compile time, e is of type Person, and the method call is determined at run time, so the getInfo() method of Student class is called—— Dynamic binding

Significance of polymorphism

Definition: a subclass object is assigned to a variable of the parent type. Generally speaking, it is to convert a subclass object into a parent object.

class Person{
    public void print() {
        System.out.println("human beings");
    }
}
class Student extends Person{
    public void print() {
        System.out.println("I am a student");
    }
}
class Teacher extends Person{
    public void print() {
        System.out.println("I'm a teacher");
    }
}
public class Test{
    public static void main(String[] args) {
        Person per=new Student();// Polymorphism of objects
        per.print();
    }
}

What should be paid attention to in the upward transformation

        1. After the upward transformation, the methods defined separately by the subclass will be lost (the parent class does not know the new properties and methods defined by the subclass)
        2. Parent class references can point to child class objects, but child class references cannot point to parent class objects (unless forced)
        3. If the method of the parent class is overridden in the subclass, the method in the subclass will be called when this method is called

So the point is, what is the significance of upward transformation?

Reduce duplicate codes
When instantiating, you can instantiate different objects according to different requirements to realize parameter unification

//Example 1 of polymorphism:
public class AnimalTest {

    public static void main(String[] args) {

        AnimalTest test = new AnimalTest();
        test.func(new Dog());


        test.func(new Cat());
    }

    public void func(Animal animal){//Animal animal = new Dog();
        animal.eat();
        animal.shout();

        if(animal instanceof Dog){
            Dog d = (Dog)animal;
            d.watchDoor();
        }
    }

    //	public void func(Dog dog){
    //		dog.eat();
    //		dog.shout();
    //	}
    //	public void func(Cat cat){
    //		cat.eat();
    //		cat.shout();
    //	}
}


class Animal{

    public void eat(){
        System.out.println("Animals: eating");
    }

    public void shout(){
        System.out.println("Animal: call");
    }


}

class Dog extends Animal{
    public void eat(){
        System.out.println("Dogs eat bones");
    }

    public void shout(){
        System.out.println("Woof! Woof! Woof!");
    }

    public void watchDoor(){
        System.out.println("Janitor");
    }
}
class Cat extends Animal{
    public void eat(){
        System.out.println("Cats eat fish");
    }

    public void shout(){
        System.out.println("Meow! Meow! Meow!");
    }
}

//Example 2:

class Order{

    public void method(Object obj){

    }
}

//Example 3:
class Driver{

    public void doData(Connection conn){//conn = new MySQlConnection(); / conn = new OracleConnection();
        //Standardized steps to manipulate data
        // conn.method1();
        // conn.method2();
        // conn.method3();

    }

}

In short, polymorphism is actually based on inheritance. For example, if we are going to visit animals in the zoo today, you are right to say that we are going to visit rabbits, sheep, lions and leopards, but you can't say that we are going to visit cars. In this case, the subclass is polymorphic: it can act as a parent in addition to using its own identity.

Comparison of method rewriting and overloading

        1. The definition details of the two are omitted

        2. From the perspective of compilation and operation:
Overloading means that multiple methods with the same name are allowed, and the parameters of these methods are different. The compiler modifies the name of the method with the same name according to different parameter tables of the method. For the compiler, these methods with the same name become different methods. Their call addresses are bound at compile time. Java overloading can include parent classes and subclasses, that is, subclasses can overload methods with different parameters of the same name of the parent class.
Therefore: for overloads, the compiler has determined the method to be called before the method call, which is called "early binding" or "static binding";

For polymorphism, the interpreter will not determine the specific method to be called until the moment of method call, which is called "late binding" or "dynamic binding".

Quote Bruce Eckel: "don't be silly. If it's not late binding, it's not polymorphic."

instanceof operator

x instanceof A: check whether x is an object of class A, and the return value is boolean.     
It is required that the class to which x belongs and class A must be the relationship between subclass and parent class, or compilation error.
If x belongs to subclass B of class A, the value of x instanceof A is also true.

public class Person extends Object {...}
public class Student extends Person {...}
public class Graduate extends Person {...}

public class Test {

    public void method(Person e) {
        if (e instanceof Person){
            // Handling objects of the Person class and its subclasses
        } 

        if (e instanceof Student){
            //Working with Student class and its subclass objects
        } 

        if (e instanceof Graduate){
            //Handles the Graduate class and its subclass objects
        }

    }
}

Object type conversion

Casting of basic data type:
Automatic type conversion: data types with small capacity can be automatically converted to data types with large capacity;
For example, long = 20; double d=12.0f
Forced type conversion: data types with large capacity can be cast into data types with small capacity;
For example, float f=(float)12.0; int a=(int)1200L

Casts on Java objects are called shapes:
The type conversion from subclass to parent class can be carried out automatically;
The type conversion from parent class to child class must be realized through modeling (forced type conversion);
Conversion between reference types without inheritance relationship is illegal;
Before modeling, you can use the instanceof operator to test the type of an object;

Example code:

public class ConversionTest {
    public static void main(String[] args) {
        double d = 13.4;
        long l = (long) d;
        System.out.println(l);
        
        int in = 5;
        // boolean b = (boolean)in;
        
        Object obj = "Hello";
        String objStr = (String) obj;
        System.out.println(objStr);
        
        Object objPri = new Integer(5);
        // Therefore, the following code throws a ClassCastException exception at runtime
        String str = (String) objPri;
    }
}
public class Test {
    public void method(Person e) { // Let there be no getschool() method in the Person class
        // System.out.pritnln(e.getschool()); // Illegal, compile time error
        if (e instanceof Student) {
            Student me = (Student) e; // Cast e to Student type
            System.out.pritnln(me.getschool());
        }
    }
    public static void main(String[] args){
        Test t = new Test();
        Student m = new Student();
        t.method(m);
    }
}
public class PersonTest {

    public static void main(String[] args) {
        // Object polymorphism: the reference of the parent class points to the object of the child class
        Person p = new Man();

        // After the polymorphism of the object, the memory actually loads the properties and methods unique to the subclass. However, because the variable is declared as the parent type, only the properties and methods declared in the parent class can be called during compilation. Subclass specific properties and methods cannot be called.

        // How can I call subclass specific properties and methods?
        // Transition down: use a cast type converter.
        Man m1 = (Man)p2;
        m1.earnMoney();
        m1.isSmoking = true;

        //When using strong conversion, an exception of ClassCastException may occur. Therefore, you need to judge through instanceof before strong rotation
        // Woman w1 = (Woman)p2;
        // w1.goShopping();
    }
}

Polymorphic written test questions

//Written examination questions for examination:
public class InterviewTest1 {

    public static void main(String[] args) {
        Base base = new Sub();
        base.add(1, 2, 3);

        // Sub s = (Sub)base;
        // s.add(1,2,3);
    }
}

class Base {
    public void add(int a, int... arr) {
        System.out.println("base");
    }
}

class Sub extends Base {

    public void add(int a, int[] arr) {
        System.out.println("sub_1");
    }

    //	public void add(int a, int b, int c) {
    //		System.out.println("sub_2");
    //	}

}

Keywords: Java Back-end

Added by tlchung on Tue, 25 Jan 2022 19:14:23 +0200