Herencia y polimorfismo de la clase JAVA

Herencia y polimorfismo de la clase JAVA

El contenido incluido no es exhaustivo. Se omiten algunas gramáticas de herencia simples en el frente y se registran principalmente algunos lugares ininteligibles. Libro de referencia: "Java Core Technology Volume I"

1. Comprender correctamente el polimorfismo

Una variable de objeto puede indicar una variedad de tipos reales de fenómenos llamados polimorfismo (polimorfismo), puede seleccionar automáticamente el método apropiado en tiempo de ejecución, llamado enlace dinámico (enlace dinámico).

Hay tres elementos del polimorfismo:

  1. Debe haber una relación de herencia
  2. Debe haber subclases que anulen los métodos del miembro de la clase principal
  3. Debe haber un tipo de datos principal para hacer referencia a una subclase

Después del polimorfismo, el tipo de datos principal no puede utilizar las propiedades y métodos únicos de la subclase .

Para castaño, la Managerclase es employeeuna subclase de la clase que anula el getSalarymétodo, por lo que el employeetipo de staff[0]llamada getSalaryes exhibir un polimorfismo, pero staff[0]no puede llamar a Managerlos métodos específicos de la clase.

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());
            }
    }
}

Con respecto a ** override (override) **, vale la pena señalar que la visibilidad de los métodos de subclase no puede ser menor que la de los métodos de superclase.

Por ejemplo, el método de superclase es público y el método de subclase también debe declararse como público.

2. Conversión de tipo forzada

Cada variable de objeto tiene un tipo.Cuando se almacena un valor en la variable, el compilador comprobará si promete demasiado.

Si se asigna una referencia de una subclase a una variable de superclase, el compilador lo permite (como la castaña polimórfica anterior), pero cuando se asigna una referencia de una superclase a una variable de subclase, es demasiado prometedor. Debe ser una conversión de tipo forzada.

Hay dos puntos a tener en cuenta:

  • La coerción solo se puede realizar dentro de la jerarquía de herencia
  • Los lanzamientos pueden fallar, por lo que antes de hacerlos es necesario que el instanceofoperador detecte
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. Clases y métodos finales

A veces, no queremos que una determinada clase defina una subclase. Este tipo de clase que no permite la extensión se llama clase final. Solo necesitamos usar el modificador final al definir la clase.

De manera similar, si no desea que se anulen los métodos de la clase, también podemos usar el modificador final al definir el método, pero esto destruirá el polimorfismo (por supuesto, muchos programadores sienten que el polimorfismo no es necesario).

4. Clase abstracta

En términos generales, la clase alta es más general y puede ser más abstracta. Desde cierto punto de vista, la clase ancestral es más general. La gente generalmente solo la usa como una clase base para derivar otras clases, no para construir la clase deseada. el ejemplo específico , que es una clase abstracta.

Por ejemplo, construimos una clase abstracta para personas Person, colocaremos algunos atributos comunes de clase abstracta de alto nivel, como nombre name; luego agregamos un getDescriptionmétodo para obtener una descripción de la persona, pero teniendo en cuenta la necesidad de adoptar subclases concretas. diferentes formas de descripción, no podemos definir este método, por lo que las subclases anulan este método, entonces necesita usar abstractpalabras clave.

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;
    }
}

Y la propia clase que contiene uno o más métodos abstractos debe declararse como abstract

Entonces podremos heredar la clase abstracta que define una subclase (la nota debe anular todos los abstractmétodos, ¡o la subcategoría seguirá siendo abstracta!)

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);
    }
}

De esta manera, hemos definido dos subclases concretas basadas en la clase abstracta.

Las clases abstractas no pueden crear instancias de objetos, pero podemos definir variables de clases abstractas para referirse a objetos de subclases no abstractas, por ejemplo:

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

5. Superclase de todas las clases: Objeto

La clase de objeto es la superclase de todas las clases en Java

5.1 método igual

El método equals en la clase Object se usa para detectar si un objeto es igual a otro objeto, y su método de implementación es determinar si las referencias de dos objetos son iguales . Pero a menudo necesitamos detectar la igualdad de los objetos en función de su estado . Si dos objetos están en el mismo estado, se consideran iguales.

Por lo tanto, necesitamos reescribir el método equals heredado de Object. Pero antes de eso, necesito distinguir ==la euqualsdiferencia.

  • Para el tipo básico (char, boolean, byte, short , int, long, float, double) , no es un objeto, no puede usar el equalsmétodo, que se almacena en el grupo de constantes, usando ==la determinación de vez en cuando se determina a partir del valor.
  • Para los objetos generales almacenados en el montón, cuando se usa ==cuando se juzga la determinación si la dirección del montón en memoria es igual, mientras que cuando equalsel tiempo de juicio, llama a la clase definida en el equalsmétodo para determinar si el peso no es una clase. equalsmétodo de escritura , llamará a su equalsmétodo de superclase para todos los tipos de superclase: Objeto, su equalsenfoque es ==, aquí está su fuente. (Algunas clases predefinidas, como String, han logrado un buen equalsmétodo basado en estados )

08cjsA.png

  • Para tipos básicos de empaque, puede almacenarse en la pila, puede almacenar el grupo constante, su tamaño se determina con Integerun ejemplo, que es [-128,127] en el rango del grupo constante, almacenamiento más allá En la pila, podemos ver el castaño de abajo muy claramente.
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
    }
}

Entendiendo ==y equalsdespués de una diferencia, podemos dar nuestra clase anula equalsel método, principalmente porque tal idea a continuación (tiene una clase Empleado, por ejemplo).

    ...
    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;
    }
    ...

Probemos brevemente:

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
    }
}

Eso es ~

5.2 método hashCode

Cómo obtener el código hash

El método hashCode se define en Object, y su valor se deriva de su dirección de almacenamiento , y el valor hash que normalmente necesitamos se deriva en función de su contenido , por lo que debemos reescribirlo al crear una clase.

El método hashCode se ha reescrito en algunas clases predefinidas, como la clase String:

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

¿Y las clases que nos definimos?

Nuestras clases personalizadas generalmente se componen de tipos de datos básicos y algunas clases predefinidas, por lo que solo necesitamos combinar su código hash.

Mire directamente el siguiente código o tome la clase Empleado como ejemplo:

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

Luego prueba el hashCode que implementamos

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
    }
}

¡genial!

5.3 método toString

También hay un método muy importante en Object :, toStringel método predeterminado es el siguiente:

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

Cuando queremos imprimir una clase LocalDate, podemos escribir fácilmente el siguiente código:

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

Sabemos que solo la cadena String puede simplemente realizar la operación "+", pero ¿por qué LocalDate también funciona?

Y las cadenas juntas porque, el compilador de Java llamará automáticamente mientras un objeto por su toStringmétodo operador "+" , es muy conveniente de usar.

Para estas clases predefinidas, hemos reescrito una buena toStringforma para nuestras clases personalizadas, necesita reescribir las nuestras, la mayoría de los toStringmétodos siguieron este formato: nombre de la clase, luego cuando un par de corchetes El valor del campo.

En el código anterior, tome la clase Empleado como ejemplo:

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

Pruébalo ~

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

Resultado de salida:

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

Nada mal ~

Supongo que te gusta

Origin blog.csdn.net/weixin_44338712/article/details/108917536
Recomendado
Clasificación