Использование признаков с тем же именем и декларацией - PullRequest
0 голосов
/ 30 апреля 2020

У меня есть абстрактный класс Person и две черты Employee и Student

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

И мне нужно создать 2 экземпляра, используя эти две черты

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

Я получаю ошибку:

... наследует конфликтующие члены: ленивый налог на стоимость с признаком Сотрудник типа Double и сальдо стоимости с признаком Ученик типа Double ...

Как использовать две черты с поля с одинаковыми именами?

Ответы [ 2 ]

2 голосов
/ 30 апреля 2020

Идеальный способ - создать отдельную черту для налога под названием Tax и расширить Employee и Student от этой базовой черты. Черты в идеале должны действовать как интерфейс и не должны иметь фактической реализации. Реализация должна быть частью класса, который расширяет эту черту.

Следующая реализация заботится об этом

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

1 голос
/ 30 апреля 2020

Первая проблема заключается в том, что вы пытаетесь переопределить val с помощью var, а вторая проблема называется проблемой алмазов. Проблема может быть решена следующим образом:

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
}

Здесь вы можете найти похожее решение проблемы: http://eed3si9n.com/curious-case-of-putting-override-modifier

И вы можете узнать больше о линеаризации здесь: http://eed3si9n.com/constraining-class-linearization-in-Scala И здесь: https://www.artima.com/scalazine/articles/stackable_trait_pattern.html

...