代码之家  ›  专栏  ›  技术社区  ›  Jacob Wang

Scala-构造函数中的抽象类型

  •  0
  • Jacob Wang  · 技术社区  · 8 年前

    考虑以下代码:

    sealed trait SpecieType
    case class Mammal() extends SpecieType
    case class Insect() extends SpecieType
    
    abstract class Specie(name: String, specie: T) {
      type T <: SpecieType
    }
    

    然而,这无法编译(第5行),因为抽象类型是在内部定义的 Specie 类定义。

    我需要改变什么才能使这项工作正常进行?

    我之所以需要一个抽象类型,是因为我在编译时需要其参数的类型(以执行类型类模式的隐式查找)。基本上,我需要这样做: implicitly[SomeTypeClass[Specie#T]] 哪里 SomeTypeClass 是一个类型类 SpecieType 机具。

    1 回复  |  直到 8 年前
        1
  •  2
  •   sjrd    8 年前

    不幸的是,这是类主体作为构造函数产生严重限制的情况之一。你想达到的目标本身是不可能的。

    据我所知,有两种主要的选择。一种是,正如@cchantep在注释中建议的那样,使用类型参数而不是抽象类型成员。警告是,它更改了 Specie ,这可能会使您的生活在程序的其余部分变得乏味。

    另一种选择允许您保留类型成员版本,但代价是有点不安全。这可能是可以接受的,因为你有一个抽象类,所以只有子类需要小心:

    sealed abstract class Specie(name: String, _specie: SpecieType) {
      type T <: SpecieType
    
      val specie: T = _specie.asInstanceOf[T]
    }
    
    class MammalSpecie extends Specie("Mammal", Mammal()) {
      type T = Mammal
    }
    

    如果你能忍受丑化子类的定义,你可以重新实施安全 Specie公司 ,使用中间抽象类:

    sealed abstract class Specie(name: String, _specie: SpecieType) {
      type T <: SpecieType
    
      val specie: T = _specie.asInstanceOf[T]
    }
    
    abstract class SpecieBase[U <: SpecieType](name: String, _specie: U)
        extends Specie(name, _specie) {
      type T = U
    }
    
    class MammalSpecie extends SpecieBase("Mammal", Mammal())
    

    自从 Specie公司 它本身是密封的,从 Specie公司 实际上是从 SpecieBase ,未密封。 规格基础 加强安全 Specie公司 无法强制执行。