【问题标题】:F-bounded type generic vs abstract typeF 有界类型泛型与抽象类型
【发布时间】:2017-05-19 01:34:09
【问题描述】:

我有一个特质和一个案例类:

trait Foo[T <: Foo[T]] {
  def self: T
}

case class Bar() extends Foo[Bar] {
  def self = this
}

我想创建一个可以采用扩展Foo 的案例类的类型。如果我使用泛型创建特征:

trait TT[Key <: Foo[Key]] {
  def f(key: Key) = {
    key
  }
}

val tt = new TT[Foo[_]]{}
tt.f(Bar())

它工作正常,但我不知道如何使用抽象类型来表达同样的事情:

trait T {
  type Key <: Foo[Key]
  def f(key: Key) = {
    key
  }
}
val t = new T{}
t.f(Bar()) //doesn't compile

为什么第二个版本不行?

编辑:

正如@Jasper-M 指出的那样,第一个版本也不起作用,这里是更新的版本:

import scala.language.existentials

trait Foo[+T <: Foo[T]] {
  def self: T
}

object Foo {
  type Any = Foo[T] forSome { type T <: Foo[T] }
}

val tt = new TT[Foo.Any]{}
tt.f(Bar())

【问题讨论】:

  • 我可以问一下,鉴于 f 有界泛型已经为您提供了所需的内容,为什么您会出于好奇而想要这样做?
  • 我的大部分代码都使用抽象类型,如果不可能,我需要使用泛型重写所有代码。
  • 你使用抽象类型有什么原因吗?
  • 这对我来说更方便,因为类型是在层次结构底部的代码中指定的,它不会作为参数暴露给客户端。
  • 顺便说一句,你的“工作正常”版本也不能为我编译。

标签: scala generics


【解决方案1】:

您必须将Key 类型初始化为Bar

scala> val t = new T { type Key = Bar }
t: T{type Key = Bar} = $anon$1@2c34c819

scala> t.f(Bar())
res0: t.Key = Bar()

【讨论】:

    猜你喜欢
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多