特征中的 Scala 泛型类型别名 - 类型参数数量错误



我认为以下代码肯定会起作用,但它报告错误"类型参数数量错误。预期:2,实际:1"

trait MyTrait[T] {
  type Things = Seq[T]
  type Cache[K] = scala.collection.mutable.HashMap[K, Option[Things]]
}
abstract class MyImpl[T] extends MyTrait[T] {
  val cache = new Cache[String]
}

我通过将其更改为:

trait MyTrait[T] {
  type Things = Seq[T]
  type Key
  type Cache = scala.collection.mutable.HashMap[Key, Option[Things]]
}
abstract class MyImpl[T] extends MyTrait[T] {
  type Key = String
  val cache = new Cache
}

但是我对斯卡拉斯类型系统有什么误解?为什么我不能在"MyImpl"中创建不同的 Cache[T] 实现。例如,为什么我不能在MyImpl中创建Cache[String]和Cache[Int]?

最后,在 Scala 中实现这种结构的最佳方式是什么?

正如我在评论中所说,代码确实可以编译(使用 scalac):

trait MyTrait[T] {
  type Things = Seq[T]
  type Cache[K] = scala.collection.mutable.HashMap[K, Option[Things]]
}
abstract class MyImpl[T] extends MyTrait[T] {
  val cache = new Cache[String]
}

将类型参数视为函数参数。在这里,您有 2 件事有所不同,Seq 中包含的 T 和用作缓存键的 K。对于一个函数,你可以写: myTraitFactory(t, k)对于类型参数,您可以编写MyTrait[T, K]

这给了我们:

trait MyTrait[K, T] {
  type Things = Seq[T]
  type Cache = scala.collection.mutable.HashMap[K, Option[Things]]
}
abstract class MyImpl[K, T] extends MyTrait[K, T] {
  val cache = new Cache
}
class MyCache extends MyImpl[String, Cacheable]

你实际上不需要编写 Cache[K],因为 K 已经在类的类型参数中定义为参数。MyImpl 保持 2 种类型 K 和 T 未知,而 MyCache 将这些类型固定到具体的类中,不再抽象。

您可以像在

trait/class body 中对 Key 所做的那样声明它们,而不是显式声明类型参数,并将它们保持抽象,直到您在子类或子特征中修复它们的值。

trait MyTrait {
  type T
  type Key
  type Things = Seq[T]
  type Cache = scala.collection.mutable.HashMap[Key, Option[Things]]
}
abstract class MyImpl extends MyTrait {
  type Key = String
  val cache = new Cache // using Strings as keys
}
class MyCache extends MyImpl {
  type T = Cacheable
}

您的缓存可能不需要存储与无值(None)关联的键,否则cache.get将返回Option[Option[Seq[T]]],这看起来不容易使用,所以最后对于缓存,我会写:

trait MyTrait[K, T] {
  type Things = Seq[T]
  type Cache = scala.collection.mutable.HashMap[Key, Things]
}
这是

Intellij IDEA的一个错误。下面的代码可以编译:

trait MyTrait[T] {
  type Things = Seq[T]
  type Cache[K] = scala.collection.mutable.HashMap[K, Option[Things]]
}
abstract class MyImpl[T] extends MyTrait[T] {
  val cache = new Cache[String]
}

相关内容

最新更新