Explicación detallada de la herencia de Scala.

1. Extienda la clase
Use la palabra clave extend para extender la clase

class Employee extends Person {
	var age = 10
	...
}

En la definición, proporcione los campos y métodos requeridos por la subclase pero no la superclase, o anule los métodos de la superclase. Al igual que Java, puede declarar una clase como final, para que no se pueda extender, y puede declarar el método o campo como final para asegurarse de que no se puedan anular.

2. Método de reescritura
Para anular un método no abstracto en scala, debe usar el modificador de anulación, por ejemplo:

public class Person {
  ...
  override def toString = getClass.getName + "[name=" + name + "]"
}

El modificador de anulación puede dar un mensaje de error en muchas situaciones comunes:
1. Escribe mal el nombre del método a reescribir
2. Usa accidentalmente el tipo de parámetro incorrecto en el nuevo método
3. Introduce uno nuevo en la superclase Método, y este nuevo método entra en conflicto con los métodos de las subclases

El método de llamar a la superclase en scala es el mismo que java, usando la palabra clave super:

public class  Employee extends Person {
	...
	override def toString = super.toString
}

super.toString llamará al método toString de la superclase, es decir, Person.toString.

3. Verificación y conversión de tipos Para
probar si un objeto pertenece a una clase dada, puede usar el método isInstanceOf. Si la prueba es exitosa, puede usar el método asInstanceOf para convertir la referencia en una referencia de subclase.

if (p.isInstanceOf[Employee]) {
  val s = p.asInstanceOf[Employee]  //s类型为Employee
}

Si p apunta a un objeto de clase y subclases de Empleado (por ejemplo, si hay un Administrador), entonces p.isInstanceOf [Empleado] tendrá éxito y devolverá verdadero.
Si p es nulo, p.isInstanceOf [Empleado] devolverá falso, y p.asInstanceOf [Empleado] devolverá nulo.
Si p no es un Empleado, entonces p.asInstanceOf [Empleado] lanzará una excepción.
Si desea probar que p apunta a un objeto Empleado pero no a su subclase, puede:

if (p.getClass == classOf[Employee])

El método classOf se define en el objeto scala.Predef, por lo que se introducirá automáticamente.
La verificación y conversión de tipos de Scala en comparación
Inserte la descripción de la imagen aquí
con Java: pero en comparación con la verificación y conversión de tipos, la coincidencia de patrones suele ser una mejor opción, como por ejemplo:

p match {
  case s: Employee => ... 
  case _ => ...
}

4. Campos y métodos protegidos
Al igual que Java, puede declarar campos o métodos como protegidos. Se puede acceder a dichos miembros desde cualquier subclase, pero no se puede ver desde otras ubicaciones.
A diferencia de Java, los miembros protegidos no son visibles para el paquete al que pertenece la clase. Si necesita esta visibilidad, puede usar el modificador de paquete.
También hay un [this] protegido, que establece el permiso de acceso al objeto actual, similar al privado [this].

5. Construcción de superclases
Sabemos que una clase tiene un constructor principal y cualquier número de constructores auxiliares. Cada constructor principal debe
comenzar con una llamada a un constructor auxiliar o constructor principal previamente definido. La consecuencia de esto es que los constructores auxiliares nunca pueden llamar directamente a los constructores de superclase.
Los constructores auxiliares de subclases eventualmente llamarán al constructor principal. Solo el constructor principal puede llamar al constructor de la superclase.
El constructor principal está entrelazado con la definición de clase. La forma de llamar al constructor de la superclase también está entrelazada.
Tales como:

class Employee(name: String,age: Int,val salary: Double) extends Person(name,age)

Este código define una subclase Empleado y un constructor principal Empleado (nombre: Cadena, edad: Int, val salario: Doble) que
llama al constructor de la superclase. Entrelazar la clase y el constructor puede hacer que el código sea más conciso , Puede ser mejor entender los parámetros del constructor principal como los parámetros de la clase. Por ejemplo, la clase Employee tiene tres parámetros:
nombre, edad, salario, dos de los cuales se pasan a la superclase. Si es Java, será mucho más complicado:

public class Employee extends Person {
  private double salary;
  public Employee(String name,Int age, double salary) {
	super(name,age);
	this.salary = salary;
  }
}

La clase Scala puede extender la clase Java. En este caso, su constructor principal debe llamar a un método de construcción de la superclase Java, como:

class Square(x: Int,y: Int,width: Int) extends java.awt.Rectangle(x,y,width.width)

6. Campo de reescritura El campo
Scala consta de un campo privado y un método de cambio de valor / valor. Puede usar otro campo val con el mismo nombre para reescribir un valor (o def sin parámetros).
La subclase tiene un campo privado y un método getter público, y este método getter anula el método getter de superclase. Tales como:

class Person(val name: String) {
  override def toString = getClass.getName + name
}
class SecretAgent(codename: String) extends Person(codename) {
  override val name = "secret"
  override val toString = "secret"
}

El ejemplo anterior muestra el mecanismo de reescritura, pero es más rígido y es más común usar val para reescribir defs abstractas, como:

abstract class Person {
  def id: Int   //每个人都有某一种方式计算id
  ...
}
class Student(override val id: Int) extends Person

La reescritura tiene las siguientes restricciones:
1.def solo puede reescribir otro def
2.val solo puede reescribir otro val o def sin parámetros
3.var solo puede reescribir otra var abstracta

7. Subclases anónimas Al igual que
Java, se puede crear una subclase anónima incluyendo bloques de código con definiciones o reescrituras, tales como:

val alien = new Person("Fred") {
  def greeting = "Grettings, Earthing, my name is Fred"
}

Técnicamente hablando, esto crea un objeto de tipo de estructura, que se marca como Persona {def greeting: String}, podemos usar este tipo como la definición del tipo de parámetro:

def meet(p: Person{def greeting: String}) {
  println(p.name + "says" + p.greeting)
}

8. Clase abstracta
Al igual que Java, puede usar la palabra clave abstracta para marcar una clase que no se puede instanciar, generalmente porque uno o más de sus métodos no están completamente definidos, como:

abstract class Person(val name: String) {
  def id: Int //没有方法体,这是一个抽象方法
}

Aquí decimos que todos tienen una identificación, pero no sabemos cómo calcularla. Cada subclase de persona específica debe proporcionar un método de identificación. A diferencia de Scala, a diferencia de Java, no necesitamos usar la palabra clave abstracta , Solo omita el cuerpo del método, pero como Java, si hay al menos un método abstracto en una clase, la clase debe declararse como abstracta.
Al anular el método abstracto de una superclase en una subclase, no es necesario usar la palabra clave de anulación.

class Employee(name: String) extends Person(name) {
  def id = name.hashCode //无需override
}

9. Campo abstracto
Además de los métodos abstractos, una clase también puede tener un campo abstracto, un campo abstracto es un campo sin un valor inicial, como:

abstract class Person {
 val id: Int   //没有初始化,这是一个带有抽象的getter方法的抽象字段
 var name: String //另一个抽象字段,带有抽象getter和setter方法
}

Esta clase define métodos getter abstractos para los campos id y name, y métodos setter abstractos para el campo name. La clase Java generada no tiene campos.
Las subclases específicas deben proporcionar campos específicos, como:

class Employee(val id: Int) extends Person { //子类有具体的id属性
  var name = ""  //和具体点的name属性
} 

Al igual que con los métodos, la palabra clave de anulación no es necesaria cuando se reescribe el campo abstracto de una superclase en una subclase.

10. Orden de construcción y definición
por adelantado Cuando reescribimos val en la subclase y el constructor en la superclase también usa este valor, puede causar algunos malos resultados.
Por ejemplo, los animales pueden percibir los alrededores, suponiendo que el animal predeterminado puede ver 10 unidades al frente, entonces podemos:

class Creature {
  val range: Int = 10
  val env: Array[Int] = new Array[Int](range)
}
//但蚂蚁是近视的
class Ant extends Creature {
  override val range = 2
}

Ahora enfrentaremos un problema, el valor del rango se usa en la inicialización del constructor de superclase, y el constructor de superclase se ejecuta antes que el constructor de subclase. El proceso específico es el siguiente:
1. El constructor de Ant llama al constructor de Creature antes de hacer su propia construcción.
2. El constructor de Creature establece su campo de rango en 10.
3. Para inicializar la matriz env, el constructor del creador llama al evaluador range ().
4. Este método se reescribe para generar el valor del campo de rango de la clase Ant (aún no inicializado).
5. El método de rango devuelve 0 (este es el valor inicial de todos los campos enteros cuando se asigna espacio al objeto).
6. env se establece en una matriz de longitud 0.
7. El constructor Ant continúa ejecutándose, estableciendo su campo de rango en 2.
Aunque el campo de rango puede parecer 2, pero env está configurado en una matriz de longitud 0, la lección aquí es que el valor de val no debe confiarse en el constructor.
En Java, cuando llama a un método en el constructor de la superclase, encontrará problemas similares. El método llamado puede ser reescrito por la subclase, por lo que puede no comportarse como se esperaba. De hecho, este es el núcleo del problema Donde, la expresión de rango llama al método getter.
Existen las siguientes soluciones:
1. Declarar val como final. Seguro pero no flexible.
2. Declarar val como vago en la superclase. Seguro pero no eficiente.
3. Use la sintaxis predefinida en la subclase.
Defina la sintaxis de antemano para inicializar el campo val de la subclase antes de que se ejecute el constructor de la superclase:

class Ant extends {
  override val range = 2
} with Creature
14 artículos originales publicados · Me gusta1 · Visitas 684

Supongo que te gusta

Origin blog.csdn.net/qq_33891419/article/details/103853826
Recomendado
Clasificación