简体   繁体   English

基于类型参数具有不同定义的 Scala Trait

[英]Scala Trait with different def based on Type Parameter

Im trying to construct a generic DAO that is instantiated with a concrete class of either type:我试图构建一个通用的 DAO,该 DAO 使用任一类型的具体类进行实例化:

  1. Regular常规的
  2. Snappy <: Regular活泼的 <:常规

I currently have a trait DAO that describes the available methods, get/create/upsert.我目前有一个描述可用方法的特征 DAO,get/create/upsert。 At compile time I would like to change/define each of the methods based on the type parameter i am passing.在编译时,我想根据我传递的类型参数更改/定义每个方法。 Here is some code:这是一些代码:

trait Regular {
    id: int
}

trait Snap extends Regular {
    isSnappy: Boolean = true
}

trait DAO[T<: Regular] {
  def get(id: String)(implicit x: Param,ct: ClassTag[T]): Future[Either[String, T]] 
}

if the trait is Regular:如果特征是常规的:

 def get(id:String)(implicit x: Param,ct: ClassTag[T]): Future[Either[String, T]] = {
   //Handle regular trait flow
 }

if the trait is Snap <: Regular:如果特征是 Snap <: 常规:

 def get(id:String)(implicit x: Param,ct: ClassTag[T]): Future[Either[String, T]] = {
   //Handle snappy
 }

Both defs would return the same type T.两个 defs 都会返回相同的类型 T。

I want to be able to change the def at compile time, where I have knowledge of the Type parameter in the DAO.我希望能够在编译时更改 def,在那里我了解 DAO 中的 Type 参数。 Then at run time I want to be able to instantiate the class but have it handle the def based on the type being passed.然后在运行时我希望能够实例化该类,但让它根据传递的类型处理 def。

Im not sure how to handle this in scala, whether its a macro based solution, overloaded methods, some type of implicit defined for the Dao.我不确定如何在 Scala 中处理这个问题,无论是基于宏的解决方案,重载方法,还是为 Dao 定义的某种类型的隐式。 Any direction would be much appreciated!任何方向将不胜感激! Im not sure if this is a unique question but I have read through as much as I could regarding compile time definition based on type parameters while still being able to refer to the same trait (DAO in this case)我不确定这是否是一个独特的问题,但我已经尽可能多地阅读了基于类型参数的编译时定义,同时仍然能够引用相同的特征(在这种情况下为 DAO)

You probably want a typeclass for this situation.对于这种情况,您可能需要一个类型类。 There is lots to read about this out there, but here is a sample based on a cut-down version of your code.有很多关于这个的阅读,但这里有一个基于你的代码的简化版本的示例。

First define a class with all the operations that are needed:首先定义一个包含所有所需操作的类:

trait DaoOps[T] {
  def get(id: String): Int
  def create(id: String): T
  def upsert(id: String): Int
}

Then create an implicit instance of DaoOps with the implementation for each type:然后使用每种类型的实现创建一个DaoOpsimplicit实例:

trait Regular {
    def id: Int
}

object Regular {
  // DAO implementation for instances of Regular type
  implicit object dao extends DaoOps[Regular] {
    def get(id: String): Int = ???
    def create(id: String): Regular = ???
    def upsert(id: String): Int = ???
  }
}

trait Snap extends Regular {
  def isSnappy: Boolean = true
}

object Snap {
  // DAO implementation for instances of Snap type
  implicit object dao extends DaoOps[Snap] {
    def get(id: String): Int = ???
    def create(id: String): Snap = ???
    def upsert(id: String): Int = ???
  }
}

Finally, use the typeclass in the main class to select the implementation for the particular type that is being used:最后,使用主类中的 typeclass 为正在使用的特定类型选择实现:

trait DAO[T <: Regular] {
  // Select the ops for the actual type of T
  def get(id: String)(implicit ops: DaoOps[T]): Int =
    ops.get(id)
}

The implicit object s don't have to be in the companion class, but the compiler will look for them there so it avoids having to explicitly bring them into scope. implicit object不必在伴随类中,但编译器会在那里寻找它们,从而避免必须显式地将它们带入作用域。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM