2013-04-24 51 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]