scala - 定义依赖于隐式的抽象类或特征

标签 scala inheritance playframework-2.0 traits

我有这个 Play Framework 2 代码(简化):

import formatters.json.IdeaTypeFormatter._

object IdeaTypes extends Controller {

  def list = Action { request =>
    Ok(toJson(IdeaType.find(request.queryString)))
  }

  def show(id: Long) = Action {
    IdeaType.findById(id).map { ideatype =>
      Ok(toJson(ideatype))
    }.getOrElse(JsonNotFound("Type of idea with id %s not found".format(id)))
  }
}
IdeaType类扩展 Entity ,它是伴随对象,IdeaType , 扩展 EntityCompanion .

正如您所料,我在每个 Controller 中都有这种代码,所以我想将基本行为提取到特征中,如下所示:
abstract class EntityController[A<:Entity] extends Controller {
  val companion: EntityCompanion
  val name = "entity"

  def list = Action { request =>
    Ok(toJson(companion.find(request.queryString)))
  }
  def show(id: Long) = Action {
    companion.findById(id).map { entity =>
      Ok(toJson(entity))
    }.getOrElse(JsonNotFound("%s with id %s not found".format(name, id)))
  }
}

但我收到以下错误:
[error] EntityController.scala:25: No Json deserializer found for type List[A]. 
[error] Try to implement an implicit Writes or Format for this type.
[error]     Ok(toJson(companion.find(request.queryString)))
[error]              ^
[error] EntityController.scala:34: No Json deserializer found for type A.
[error] Try to implement an implicit Writes or Format for this type.
[error]       Ok(toJson(entity))
[error]                ^

我不知道如何分辨隐含的 Writes将由实现 EntityController 的类实现trait(或继承抽象类 EntityController)

- 编辑

到目前为止,我正在这样做:
abstract class CrudController[A <: Entity](
  val model: EntityCompanion[A],
  val name: String,
  implicit val formatter: Format[A]
) extends Controller {

并像这样使用它
object CrudIdeaTypes extends CrudController[IdeaType](
  model = IdeaType, 
  name = "type of idea", 
  formatter = JsonIdeaTypeFormatter
)

我无法让 Scala 使用隐式自动选择它。我试过这个导入,但没有用
import formatters.json.IdeaTypeFormatter._

最佳答案

如果您希望 Controller 类本身定义隐式,则只需声明抽象的隐式值,并在派生类中定义它们。

abstract class EntityController[A<:Entity] extends Controller {
  protected implicit def entityWriter: Writes[A]
  protected implicit def entityListWriter: Writes[List[A]]
  ...      
}

class MyEntity extends Entity {
  ...
}

class MyEntityController extends EntityController[MyEntity] {
  protected def entityWriter: Writes[MyEntity] = ...
  protected def entityListWriter: Writes[List[MyEntity]] = ...    
}

但是,在 Controller 外部定义这些隐式更实用,通常在实体的伴随对象中,以便编译器无需导入即可自动找到它们。
然后,将隐式值传递给 EntityController 的构造函数:
abstract class EntityController[A<:Entity](implicit entityWriter: Writes[A], entityListWriter: Writes[List[A]] ) extends Controller {
  ...      
}

class MyEntity extends Entity {
  ...
}
object MyEntity {
  protected implicit def entityWriter: Writes[A]
  protected implicit def entityListWriter: Writes[List[A]]
}

class MyEntityController extends EntityController[MyEntity] {
  ...
}

最后一点,可能不需要 List[MyEntity] 的隐式(因此只有 MyEntity 的隐式需要显式定义)。我没有检查过,但通常在使用这种“类型类模式”时,
框架已经为每个 List[T] 定义了一个隐式,前提是 T 有一个隐式。这可能是这种情况,虽然我没有检查过。

关于scala - 定义依赖于隐式的抽象类或特征,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12946359/

相关文章:

scala - Scala:为什么可以将Int转换为Unit?

c++ - 如何用复数和多态重载运算符?

c# - 从具有共同成员的多个类创建父类(super class)

c++ - 在C++中将子类插入到父类(super class)数组中

scala - Play Framework Scala 在后台运行作业

java - 在更改和重新加载时 Play Framework 并出现 eclipselink 错误

scala - 如何实现 ScalaTest FunSuite 以避免样板 Spark 代码和导入隐式

scala - 使用 Spark Dataframe scala 将多个不同列转换为 Map 列

scala - 诈骗 "illegal nesting"错误

playframework - 如何从 play framework 2.5.x 构建 jar