1

考虑以下类定义:

class Person[+T <: Person[T]]
class Student() extends Person[Student]
class Professor() extends Person[Professor]

我想要一个学生和教授的名单:

val persons = List(new Student(), new Professor())

但这无法编译并出现以下错误:

type arguments [Person[Person[Any]]] do not conform to class Person's type parameter bounds [+T <: Person[T]]

感谢 Daniel C. Sobral 对我之前的相关问题How to define case classes with members with unbound type parameters?的回答。我知道存在类型会在这里解决问题。这编译:

val persons = List[Person[T] forSome {type T <: Person[T]}](new Student(), new Professor())

<: Person[T]问题是由类 Person 的声明的类型参数中的上限引起的。删除上限可以让编译器推断列表的类型参数,使其编译:List[Person[Person[Person[Any]]]]据我所知。

问题

  1. 为什么编译器不能推断出可以编译的列表的任何类型?
  2. 存在类型是最不冗长的,而且可能更棘手(参见丹尼尔对我上面链接的上一个问题的回答):是否有替代显式存在类型来创建学生和教授列表?
4

1 回答 1

1

我相信你在第二条评论中已经提到了一个可能的替代方案

val persons = List[Person[_]](new Student(), new Professor())

但据我了解,Scala 中执行此类操作的惯用方式是在 Person 中使用类型声明,并在 Student 和 Professor 中定义它:

trait Person {
  type PersonImpl <: Person
  def colleagues: Seq[PersonImpl]
}

class Student extends Person {
  type PersonImpl = Student
  def colleagues = Seq(this)
}

class Professor extends Person {
  type PersonImpl = Professor
  def colleagues = Seq(this)
}

val persons = List(new Student, new Professor)

Martin Odersky 在 Scala 语言中也提到,他正在考虑统一类型参数和抽象类型成员

根据您的实际用例,最简单的解决方案可能是依赖方法覆盖:

trait Person {
  def colleagues: Seq[Person]
}

class Student extends Person {
  def colleagues: Seq[Student] = Seq(this)
}

class Professor extends Person {
  def colleagues: Seq[Professor] = Seq(this)
}

val persons = List(new Student, new Professor)
于 2012-04-26T07:41:33.673 回答