我认为以下代码可以肯定,但它会报告错误"错误的类型参数数量。预期: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
}
但是我对scalas类型系统的误解是什么?为什么我不能在' MyImpl'中创建不同的Cache [T]实现。例如。为什么我不能在MyImpl中创建Cache [String]和Cache [Int]?
最后,在Scala中实现这种结构的最佳方法是什么?
答案 0 :(得分:3)
正如我在评论中所说,代码确实编译(使用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]
}
答案 1 :(得分:0)
将类型参数视为函数参数。这里有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体中使用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]
}
答案 2 :(得分:0)
这是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]
}