2013-04-24 48 views
4

我正在为scala 2.10.1中的一些实体编写通用缓存。目前,我正在使用google番石榴的CacheBuilder,因为在scala生态系统中没有太多选项。scala 2.10类型不匹配使用google guava的CacheBuilder

代码:

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 <:对象是这样的:

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

如果代码片段在语法上是正确的,那将是最好的。代码中的两个连续时段('.')无法编译。此外,你的代码_suggests_,但没有说明'K'和'E'是绑定在某个封闭结构中的类型参数。你的正确和完整的代码片段,以便人们复制和修改你的原代码? – 2013-04-24 15:55:12

+0

对不起。也使用类声明更新了代码。 – adivis 2013-04-25 07:43:21

回答

1

如果你不介意有点丑演员,你可以得到这个工作。主要问题是CacheBuilder上的build函数返回一个与[Object,Object]类型绑定的缓存。在斯卡拉,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] 
+0

我这样做,并得到第二个错误。更新了问题以反映相同。我想如果我将类型边界设置为<:Object,几乎所有的任何属性都是禁止的,这不是我想要的。 – adivis 2013-04-25 07:45:00

2

CacheBuilder需要一个对象/ 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]