我正在为scala 2.10.1中的一些实体编写通用缓存。目前,我正在使用google Guava的CacheBuilder,因为scala生态系统中的选项不多。
代码:
trait CachedEntity[E <: KeyedEntity[K],K] {
def lookup(id:K):E
def getElem(id:K):Option[E] = Try(elemCache.get(id)).toOption
val elemCache = CacheBuilder.newBuilder().maximumSize(10).expireAfterWrite(1,TimeUnit.MINUTES).build(
new CacheLoader[K,E] {
def load(key:K) = {
println("Looking Up key:" + key + "in Class:" + this.getClass.getName)
lookup(key)
}
}
)
}
trait LongKeyed[E<: KeyedEntity[Long],Long] extends CachedEntity[E,Long]
然而,sbt抛出错误:
[error] KEHCaching.scala:16: type mismatch;
[error] found : id.type (with underlying type K)
[error] required: Object with K
[error] def getElem(id:K):Option[E] = Try(elemCache.get(id)).toOption
[error] ^
[error] one error found
有什么想法吗?即使我像这样添加K&lt;:Object:
trait CachedEntity[E <: KeyedEntity[K],K <:Object] {
我收到此错误
[error] KEHCaching.scala:27: type arguments [E,Long] do not conform to trait CachedEntity's type parameter bounds [E <: org.squeryl.KeyedEntity[K],K <: Object]
[error] trait LongKeyed[E<: KeyedEntity[Long],Long] extends CachedEntity[E,Long]
[error] ^
[error] one error found
答案 0 :(得分:3)
CacheBuilder需要Object / AnyRef。 您可以使用java.lang.Long而不是scala.Long,如下所示; Scala会根据需要自动装箱/取消装箱。
import scala.util.Try
import java.util.concurrent.TimeUnit
import java.lang.{Long => JLong}
trait KeyedEntity[K]
trait CachedEntity[E <: KeyedEntity[K], K <: AnyRef] {
def lookup(id:K):E
def getElem(id:K):Option[E] = Try(elemCache.get(id)).toOption
val elemCache = CacheBuilder.newBuilder().maximumSize(10).expireAfterWrite(1,TimeUnit.MINUTES).build(
new CacheLoader[K,E] {
def load(key:K) = {
println("Looking Up key:" + key + "in Class:" + this.getClass.getName)
lookup(key)
}
}
)
}
trait LongKeyed[E <: KeyedEntity[JLong]] extends CachedEntity[E,JLong]
答案 1 :(得分:1)
如果你不介意一点丑陋的演员,你可以让它发挥作用。主要问题是build
上的CacheBuilder
函数返回与类型[Object,Object]
绑定的缓存。在Scala中,AnyVal
不是从Object派生的,因此它不起作用。但是我嘲笑了下面的代码示例,以展示如何通过一些丑陋的演员来解决这个限制:
trait CachedEntity[E <: KeyedEntity[K], K] {
def lookup(id:K):E
def getElem(id:K):Option[E] = Try(elemCache.get(id)).toOption
val elemCache = CacheBuilder.newBuilder().build(
new CacheLoader[K,E] {
def load(key:K) = {
println("Looking Up key:" + key + "in Class:" + this.getClass.getName)
lookup(key)
}
}
).asInstanceOf[LoadingCache[K,E]]
}
trait LongKeyed[E<: KeyedEntity[Long]] extends CachedEntity[E,Long]
case class MyEntity(id:Long, value:String) extends KeyedEntity[Long]
class MyEntityCache extends LongKeyed[MyEntity]{
def lookup(id:Long) = MyEntity(id, "foo")
}
object CachedEntityTest{
def main(args: Array[String]) {
val cache = new MyEntityCache
val entity = cache.getElem(1)
println(entity)
}
}
//Faking this for purposes of code sample...
trait KeyedEntity[K]