【问题标题】:scala 2.10 type mismatch using google guava's CacheBuilderscala 2.10 类型不匹配使用谷歌番石榴的 CacheBuilder
【发布时间】:2013-04-24 15:39:05
【问题描述】:

我正在为 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<: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

【问题讨论】:

  • 如果代码 sn-ps 在语法上是正确的,那将是最好的。无法编译代码中的两个连续句点 (.)。此外,您的代码 suggests 但没有明确指出 KE 是绑定在某些封闭结构中的类型参数。您能否更正和完善代码片段,以便人们复制和修改您的原始代码?
  • 对不起。也用类声明更新了代码。

标签: scala guava


【解决方案1】:

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]

【讨论】:

    【解决方案2】:

    如果你不介意有点丑陋的演员表,你可以让它工作。主要问题是CacheBuilder 上的build 函数返回与[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]
    

    【讨论】:

    • 我这样做并得到了第二个错误。更新了问题以反映相同。我想如果我将类型边界设置为 <:object>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多