Inheritance and Polymorphism of JAVA Class

Inheritance and Polymorphism of JAVA Class

The content included is not comprehensive. Some simple inheritance grammars in the front are skipped, and some unintelligible places are mainly recorded. Reference book: "Java Core Technology Volume I"

1. Correctly understand polymorphism

An object variable can indicate a variety of actual types of phenomenon called polymorphism (polymorphism), can automatically select the appropriate method at runtime, called dynamic binding (dynamic binding).

There are three elements to polymorphism:

  1. There must be an inheritance relationship
  2. There must be subclasses that override the parent class member methods
  3. There must be a parent data type to refer to a subclass

After polymorphism, the parent data type cannot use the unique properties and methods of the subclass .

For chestnut, Managerclass is employeea subclass of class overrides the getSalarymethod, so as the employeetype of staff[0]call getSalaryis to exhibit a polymorphism, but staff[0]can not call Managerthe class-specific methods.

public class helloworld {
    
    
        public static void main(String[] args) {
    
    
            employee[] staff = new employee[3];
            staff[0] = new Manager("Jack", 5000, 2015, 10, 25, 2000);
            staff[1] = new employee("Bob", 3000, 2017, 8, 7);
            staff[2] = new employee("Alice", 2000, 2018, 11, 25);
            for(employee e:staff){
    
    
                System.out.println(e.getName() + "'s salary:"+e.getSalary());
            }
    }
}

Regarding **override (override)**, it is worth noting that the visibility of subclass methods cannot be lower than that of superclass methods!

For example, the superclass method is public, and the subclass method must also be declared as public.

2. Forced type conversion

Every object variable has a type. When a value is stored in the variable, the compiler will check whether you promise too much.

If a reference of a subclass is assigned to a superclass variable, the compiler allows it (such as the polymorphic chestnut above), but when a reference of a superclass is assigned to a subclass variable, too much promise. Must be forced type conversion.

There are two points to note:

  • Coercion can only be performed within the inheritance hierarchy
  • Casts may fail, so before making cast requires instanceofoperator detects
public class helloworld {
    
    
        public static void main(String[] args) {
    
    
            employee staff = new employee("Bob", 3000, 2017, 8, 7);;
            if(staff instanceof Manager){
    
       // 判断是否能够转换
                Manager boss = (Manager) staff; // 如果可以就进行转换
                boss.show();
            }
    }
}

3. Final classes and methods

Sometimes, we don't want a certain class to define a subclass. This kind of class that does not allow extension is called a final class. We only need to use the final modifier when defining the class.

Similarly, if you don't want the methods in the class to be overridden, we can also use the final modifier when defining the method, but this will destroy polymorphism (of course many programmers feel that polymorphism is not needed).

4. Abstract class

Generally speaking, the upper class is more general and may be more abstract. From a certain point of view, the ancestor class is more general. People generally only use it as a base class to derive other classes, not to construct desired the specific example , which is an abstract class!

For example, we build an abstract class for people Person, we will put on some common attributes of high-level abstract class, such as name name; then we add a getDescriptionmethod for obtaining a description of the person, but taking into account the need to adopt concrete subclasses different forms of description, we can not define this method, so that subclasses override this method, then you need to use abstractkeywords.

public abstract class Person {
    
    
    private final String name;
    public Person(String name){
    
    
        this.name = name;
    }
    public abstract void getDescription();
    public String getName(){
    
    
        return this.name;
    }
}

And, the class itself containing one or more abstract methods must be declared as abstract

Then we will be able to inherit the abstract class defines a subclass (note must override all the abstractmethods, or sub-category is still abstract!)

public class Employee extends Person {
    
          // 员工类
    private double salary;
    public Employee(String name, double salary){
    
    
        super(name);
        this.salary = salary;
    }
    public void getDescription(){
    
       // 重写抽象方法
        System.out.println(super.getName() + " is an employee with a salary of " + this.salary + "$");
    }
}
public class Student extends Person{
    
            // 学生类
    private String major;
    public Student(String name, String major){
    
    
        super(name);
        this.major = major;
    }
    public void getDescription(){
    
       // 重写抽象方法
        System.out.println(super.getName() + " is a student majoring in " + this.major);
    }
}

In this way, we have defined two concrete subclasses based on the abstract class!

Abstract classes cannot create object instances, but we can define abstract class variables to refer to objects of non-abstract subclasses, for example:

public class helloworld {
    
    
        public static void main(String[] args) {
    
    
            // 抽象类变量引用非抽象子类对象
            Person a = new Student("Alice", "compute science");
            a.getDescription();
    }
}

5. Super class of all classes: Object

Object class is the super class of all classes in Java

5.1 equals method

The equals method in the Object class is used to detect whether an object is equal to another object, and its implementation method is to determine whether the references of two objects are equal . But we often need to detect the equality of objects based on their state . If two objects are in the same state, they are considered equal.

Therefore, we need to rewrite the equals method inherited from Object. But before that, I need to distinguish ==the euqualsdifference.

  • For the basic type (char, boolean, byte, short , int, long, float, double) , it is not an object, you can not use the equalsmethod, which is stored in the constant pool, using ==the determination time to time is determined from the value.
  • For general objects stored in the heap, when used ==when determination is judged whether the in-memory heap address are equal, whereas when equalsthe time for judgment, calls the class defined in the equalsmethod to determine if weight is not a class write equalsmethod, it will call its superclass equalsmethod for all types of the superclass: Object, its equalsapproach is ==, here is its source. (Some predefined classes, such as String, has achieved a good state-based equalsmethod)

08cjsA.png

  • For basic types of packaging, it may be stored in the stack, may store the constant pool, its size is determined to Integeran example, which is [-128,127] in the range of the constant pool, storage beyond it In the pile, we can see the chestnut below very clearly.
public class helloworld {
    
    
        public static void main(String[] args) {
    
    
            Integer a = 127;    // 存储在常量池中,使用==比较的是其值
            Integer b = 127;
            System.out.println(a == b);     // 输出true

            Integer c = 128;    // 存储在堆中,使用==比较的是其堆地址
            Integer d = 128;
            System.out.println(c == d);     // 输出false

            // 使用equals方法,已预定义好,是比较其状态值(即其int值)
            System.out.println(c.equals(d));     // 输出true
    }
}

Understanding ==and equalsafter a difference, we can give our class overrides equalsthe method, mainly because such an idea below (has an Employee class, for example).

    ...
    public boolean equals(Object otherObject){
    
    
        // 1.在开始比较之前,首先比较地址值,如果地址值相等就无需后续比较了
        if(this == otherObject)
            return true;
        // 2.判断是否为空,非常重要!否则容易引发异常
        if(otherObject == null)
            return false;
        // 3.如果由子类决定相等性概念,我们就使用getClass来进行判断
        if(this.getClass() != otherObject.getClass())
            return false;
        //3*.如果由超类决定相等性概念,我们就使用instanceof来进行判断
        //if(!(otherObject instanceof Employee))
        //    return false;

        // 类型转换
        Employee other = (Employee) otherObject;
        // 4.进行状态比较
        return Objects.equals(other.getName(), this.getName()) && other.salary == this.salary;
    }
    ...

Let's test it briefly:

public class helloworld {
    
    
        public static void main(String[] args) {
    
    
            Employee a = new Employee("Bob", 2000);
            Employee b = new Employee("Bob", 2000);
            System.out.println(a.equals(b));    // true
            System.out.println(a == b);         // false
    }
}

That's it~

5.2 hashCode method

How to get the hash code

The hashCode method is defined in Object, and its value is derived from its storage address , and the hash value we usually need is derived based on its content , so we need to rewrite it when creating a class.

The hashCode method has been rewritten in some predefined classes, such as the String class:

int hash = 0;
for(int hash = 0; i < length(); i++)
    hash = 31 * hash + charAt(i);

What about the classes that we define ourselves?

Our custom classes are generally composed of basic data types and some predefined classes, so we only need to combine their hashCode.

Look directly at the following code, or take the Employee class as an example:

    ...
	public int hashCode(){
    
    
        // 使用预定义类Double和String的hashCode函数生成新的hashCode
        return 7 * Double.hashCode(this.salary) + 9 * Objects.hashCode(this.getName());
    }
	...

Then try the hashCode we implemented

public class helloworld {
    
    
        public static void main(String[] args) {
    
    
            Employee a = new Employee("Bob", 2000);
            Employee b = new Employee("Bob", 2000);
            System.out.println(a.hashCode());   // 查看a的hashCode
            System.out.println(a.hashCode() == b.hashCode());   // true 成功实现基于内容的hashCode
    }
}

great!

5.3 toString method

There is also a very important method in Object:, toStringthe default method is as follows:

    public String toString() {
    
    
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }

When we want to print a LocalDate class, we can easily write the following code:

LocalDate now = LocalDate.now();
System.out.println("现在时间是" + now);

We know that only the string String can simply perform the "+" operation, but why does LocalDate also work?

And strings together because, Java compiler will automatically call as long as an object by its operator "+" toStringmethod, it is very convenient to use.

For these predefined classes, have rewritten a good toStringway for our custom classes you need to rewrite our own, most of the toStringmethods followed this format: name of the class, then when a pair of square brackets The field value.

In the above code, take the Employee class as an example:

    ...
	public String toString(){
    
    
        return this.getClass()+"[name="+this.getName()+",salary="+this.salary+"]";
    }
	...

Try it~

public class helloworld {
    
    
        public static void main(String[] args) {
    
    
            Employee a = new Employee("Bob", 2000);
            System.out.println(a.toString());
    }
}

Output result:

class com.panfeng.Employee[name=Bob,salary=2000.0]

Not bad~

Guess you like

Origin blog.csdn.net/weixin_44338712/article/details/108917536