【问题标题】:Scala: generics confusionScala:泛型混淆
【发布时间】:2013-12-27 20:52:47
【问题描述】:

我有 A、B、C 之类的类型(彼此不相关)、一个惰性 postgresql 数据库 db(在另一个类中定义)和带有普通查询的 Slick 2.10;由于泛型,我有点困惑。我想解决以下问题:

def selectT[T](query: String, id: String): List[T] = {
    db withSession{
        Q.query[String, T](query).list(id)
    }
}

所以方法必须具有结果类型List[T]。对于查询中的 T,我将编写类型 A、B 和 C。(我已经定义了 GetResults)。所以这是可能的

if(typeOf[T] <:< typeOf[A]) //using TypeTags
    db withSession{
        Q.query[String, A](query).list(id)
    }
else if(typeOf[T] <:< typeOf[A])
    db withSession{
        Q.query[String, B](query).list(id)
    }
    ...

每个查询本身都有效,但是 selectT 的结果类型不再适合。另一方面,我不想定义像List[AnyRef]List[Any] 这样的结果类型。 此外,这些类不会从 T 继承(这很简单)。 到目前为止我的代码:

import scala.slick.session.Database
import Database.threadLocalSession
import scala.slick.jdbc.{GetResult, StaticQuery => Q}
import scala.reflect.runtime.universe._
import PostgreSQLDatabase.db

object SQLExtension{
    implicit val getAResult = GetResult(r => new A(...))
    implicit val getBResult = GetResult(r => new B(...))
    implicit val getCResult = GetResult(r => new C(...))

    def selectT[T](query: String, id: String): List[T] = {
        db withSession{
            Q.query[String, T](query).list(id)
        }
    }
}

简而言之:我需要 T 的多个边界/继承/other_soulution_concept,以便我可以在方法内处理 A、B 和 C,但仍然有 List[T] 作为外部结果类型。

谢谢你,新年快乐。

编辑:2014.01.09

@cvogt 我尝试了您的解决方案,它适用于定义。但是如果我想在其他地方调用我的函数,我会遇到问题,could not find implicit value for parameter getResult: scala.slick.jdbc.GetResult[T]not enough arguments for method selectT: (implicit getResult: scala.slick.jdbc.GetResult[T])Option[T]. Unspecified value parameter getResult. 但是我已经导入了我的 GetResults?

protected[dao] def getById(id: String): Option[T] = {
      val ret = db.selectT[T](query, id)
      ret
}

【问题讨论】:

    标签: scala generics scala-2.10 slick


    【解决方案1】:

    如果我正确理解您的目标,您只需要为 selectT 要求一个隐式 GetResult。

    ...
    import scala.slick.jdbc.GetResult
    object SQLExtension{
        implicit val getAResult = GetResult(r => new A(...))
        implicit val getBResult = GetResult(r => new B(...))
        implicit val getCResult = GetResult(r => new C(...))
    
        def selectT[T](query: String, id: String)(implicit getResult: GetResult[T]): List[T] = {
            db withSession{
                Q.query[String, T](query).list(id)
            }
        }
    }
    

    然后你可以写类似的东西

    import SQLExtensions._ // imports implicits and selectT
    val res: List[A] = selectT[A]("select * from A_TABLE where id = ?",5)
    

    【讨论】:

    • +1 您也可以使用简写def selectT[T: GetResult] 来避免输入(implicit getResult: GetResult[T])
    • @cvogt 我尝试了您的解决方案,它适用于定义。但是如果我想在其他地方调用我的函数,我会遇到问题,could not find implicit value for parameter getResult: scala.slick.jdbc.GetResult[T]not enough arguments for method selectT: (implicit getResult: scala.slick.jdbc.GetResult[T])Option[T]. Unspecified value parameter getResult. 但是我已经导入了我的 GetResults?
    • 由于某种原因,您在范围内没有隐式 GetResult。要么你在导入时做错了什么,要么你没有为你正在使用的 T 定义一个。
    • 我没有在某处定义 GetResult[T]。我只使用/导入 GetResult[A]、GetResult[B]... 如果 Scala 接受我对这些类型 A 和 B 的方法,否则它会抛出异常(一种 try-catch)。或者可能是某种 case 语句(返回 GetResult[T])
    猜你喜欢
    • 2012-03-05
    • 1970-01-01
    • 1970-01-01
    • 2015-07-11
    • 2016-09-28
    • 2011-04-25
    • 1970-01-01
    • 1970-01-01
    • 2017-07-01
    相关资源
    最近更新 更多