Tengo clase abstracta Persona y dos rasgos Empleado y Estudiante

abstract class Person(val name: String) {
  val tax: Double
}

trait Employee {
  val salary: Double;
  lazy val tax: Double = salary * 0.1;
}

trait Student {
  val tax: Double = 0.0;
}

Y necesito crear 2 instancias usando estos dos rasgos

studentEmployee = new Person("John") with Student with Employee {override var salary: Double = 1000};
employeeStudent = new Person("Mike") with Employee with Student {override var salary: Double = 1000};

Recibo error:

... hereda miembros en conflicto: impuesto sobre el valor diferido en el rasgo Empleado del tipo Doble e impuesto sobre el valor en el rasgo Estudiante del tipo Doble ...

¿Cómo puedo usar dos rasgos con campos con el mismo nombre?

0
Paweł Żurkiewicz 30 abr. 2020 a las 21:08

2 respuestas

La forma ideal es crear un Rasgo separado para impuestos llamado Tax y extender el Employee y Student desde este rasgo Base. Los rasgos idealmente deberían actuar como una interfaz y no deberían tener la implementación real. La implementación debe ser parte de la clase que extiende estos rasgos.

La siguiente implementación se encarga de esto

abstract class Person(val name: String) {
}

trait Tax {
    val tax: Double

}
trait Employee extends Tax {
  val salary : Double;
  override val tax : Double ;
}

trait Student extends Tax {
  override val tax : Double;
}

var studentEmployee = new Person("John") with Student with Employee {
                   override val salary: Double = 1000;
                   override val tax = salary * 0.1};


var employeeStudent = new Person("Mike") with Employee with Student {
                  override val salary: Double = 1000 ;
                  override val tax = 0.0};

scala> studentEmployee.tax
res42: Double = 100.0

scala> employeeStudent.tax
res43: Double = 0.0

2
Jayadeep Jayaraman 30 abr. 2020 a las 20:57

El primer problema es que está intentando anular val con var y el segundo problema se llama problema de diamante. El problema se puede resolver de la siguiente manera:

abstract class Person(val name: String) {
  val tax: Double
}

trait Employee {
  var salary: Double
  val tax: Double = salary * 0.1
}

trait Student {
  val tax: Double = 0.0
}


val studentEmployee = new Person("John") with Student with Employee {
override val tax = 2.0
  override var salary: Double = 1000
}
val employeeStudent = new Person("Mike") with Employee with Student {
  override val tax = 2.0
  override var salary: Double = 1000
}

Puede encontrar aquí una solución de problema similar: http://eed3si9n.com/curious- caso-de-poner-anulación-modificador

Y puede leer más sobre linealización aquí: http://eed3si9n.com/constraining-class -linealización-en-Scala Y aquí: https://www.artima.com/scalazine/articles/stackable_trait_pattern.html

1
Bob 30 abr. 2020 a las 20:47