使用具有相同文件名和声明的特征

Using traits with the same fileds name and declaration

我有抽象的 class 人和两个特征 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};

我收到错误:

...inherits conflicting members: lazy value tax in trait Employee of type Double and value tax in trait Student of type Double ...

如何在同名字段中使用两个特征?

第一个问题是您试图用 var 覆盖 val,第二个问题称为菱形问题。问题可以这样解决:

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

理想的方法是为税收创建一个名为 Tax 的单独特征,并从该基本特征扩展 EmployeeStudent。理想情况下,特征应该像接口一样工作,不应该有实际的实现。实现应该是扩展此特征的 class 的一部分。

下面的实现解决了这个问题

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