recorrer parte lista introduccion desde curso comentarios comentar clases cero scala inheritance case-class

parte - Herencia de clase de caso Scala



recorrer lista en scala (4)

Dado que este es un tema interesante para muchos, permítanme arrojar algo de luz aquí.

Puedes ir con el siguiente enfoque:

// You can mark it as ''sealed''. Explained later. sealed trait Person { def name: String } case class Employee( override val name: String, salary: Int ) extends Person case class Tourist( override val name: String, bored: Boolean ) extends Person

Sí, tienes que duplicar los campos. Si no lo hace, simplemente no sería posible implementar la igualdad correcta entre otros problemas .

Sin embargo, no necesita duplicar métodos / funciones.

Si la duplicación de algunas propiedades es muy importante para usted, use clases regulares, pero recuerde que no se ajustan bien a FP.

Alternativamente, puede usar composición en lugar de herencia:

case class Employee( person: Person, salary: Int ) // In code: val employee = ... println(employee.person.name)

La composición es una estrategia válida y sólida que debes considerar también.

Y en caso de que se pregunte qué significa un rasgo sellado, es algo que puede extenderse solo en el mismo archivo. Es decir, las dos clases de casos anteriores deben estar en el mismo archivo. Esto permite comprobaciones exhaustivas del compilador:

val x = Employee(name = "Jack", salary = 50000) x match { case Employee(name) => println(s"I''m $name!") }

Da un error:

warning: match is not exhaustive! missing combination Tourist

Lo cual es realmente útil. Ahora no se olvidará de tratar con los otros tipos de Person (personas). Esto es esencialmente lo que hace la clase Option en Scala.

Si eso no te importa, entonces podrías hacerlo no sellado y lanzar las clases de casos en sus propios archivos. Y tal vez vaya con la composición.

Tengo una aplicación basada en Squeryl. Defino mis modelos como clases de casos, principalmente porque considero conveniente tener métodos de copia.

Tengo dos modelos que están estrictamente relacionados. Los campos son los mismos, muchas operaciones son comunes y deben almacenarse en la misma tabla de DB. Pero hay un comportamiento que solo tiene sentido en uno de los dos casos, o que tiene sentido en ambos casos, pero es diferente.

Hasta ahora solo he usado una única clase de caso, con una bandera que distingue el tipo de modelo, y todos los métodos que difieren según el tipo de modelo comienzan con if. Esto es molesto y no del todo seguro.

Lo que me gustaría hacer es factorizar el comportamiento común y los campos en una clase de caso ancestro y hacer heredar los dos modelos reales. Pero, por lo que yo entiendo, heredar de las clases de caso está mal visto en Scala, e incluso está prohibido si la subclase es en sí misma una clase de caso (no es mi caso).

¿Cuáles son los problemas y dificultades que debería tener en cuenta al heredar de una clase de caso? ¿Tiene sentido en mi caso hacerlo?


En estas situaciones, tiendo a usar composición en lugar de herencia, es decir,

sealed trait IVehicle // tagging trait case class Vehicle(color: String) extends IVehicle case class Car(vehicle: Vehicle, doors: Int) extends IVehicle val vehicle: IVehicle = ... vehicle match { case Car(Vehicle(color), doors) => println(s"$color car with $doors doors") case Vehicle(color) => println(s"$color vehicle") }

Obviamente, puedes usar una jerarquía y combinaciones más sofisticadas, pero espero que esto te dé una idea. La clave es aprovechar los extractores anidados que proporcionan las clases de casos


Las clases de casos son perfectas para objetos de valor, es decir, objetos que no cambian ninguna propiedad y que se pueden comparar con iguales.

Pero implementar iguales en presencia de herencia es bastante complicado. Considera dos clases:

class Point(x : Int, y : Int)

y

class ColoredPoint( x : Int, y : Int, c : Color) extends Point

Entonces, de acuerdo con la definición, el ColorPoint (1,4, rojo) debe ser igual al Punto (1,4), son el mismo Punto después de todo. Entonces, ColorPoint (1,4, azul) también debería ser igual a Punto (1,4), ¿verdad? Pero, por supuesto, ColorPoint (1,4, rojo) no debe ser igual a ColorPoint (1,4, azul), ya que tienen diferentes colores. Ahí va, se rompe una propiedad básica de la relación de igualdad.

actualizar

Puede usar la herencia de los rasgos resolviendo muchos problemas como se describe en otra respuesta. Una alternativa aún más flexible es a menudo utilizar clases de tipos. Consulte ¿ Para qué sirven las clases de tipos en Scala? o http://www.youtube.com/watch?v=sVMES4RZF-8


Mi forma preferida de evitar la herencia de clase de caso sin duplicación de código es algo obvio: crear una clase base común (abstracta):

abstract class Person { def name: String def age: Int // address and other properties // methods (ideally only accessors since it is a case class) } case class Employer(val name: String, val age: Int, val taxno: Int) extends Person case class Employee(val name: String, val age: Int, val salary: Int) extends Person


Si quieres ser más refinado, agrupa las propiedades en rasgos individuales:

trait Identifiable { def name: String } trait Locatable { def address: String } // trait Ages { def age: Int } case class Employer(val name: String, val address: String, val taxno: Int) extends Identifiable with Locatable case class Employee(val name: String, val address: String, val salary: Int) extends Identifiable with Locatable