8

私はこのPlayFramework2コード(簡略化)を持っています:

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)))
  }
}

IdeaTypeclass extends Entity、およびそのコンパニオンオブジェクトIdeaType、、extends EntityCompanion

ご想像のとおり、私はすべてのコントローラーにこの種のコードを持っているので、次のような特性に基本的な動作を抽出したいと思います。

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(または抽象クラスを継承する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._
4

1 に答える 1

7

コントローラークラス自体に暗黙的な値を定義させたい場合は、抽象的な暗黙的な値を宣言し、派生クラスでそれらを定義します。

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]] = ...    
}

ただし、これらの暗黙をコントローラーの外部、通常はエンティティのコンパニオンオブジェクトで定義して、コンパイラーがインポートせずに自動的に検出できるようにする方がはるかに実用的です。次に、暗黙の値を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の暗黙のみを明示的に定義する必要があります)。私はチェックしていませんが、通常、この「タイプクラスパターン」を使用する場合、Tの暗黙があれば、フレームワークは各List [T]の暗黙をすでに定義しています。これは、チェックしていませんが、おそらく当てはまります。

于 2012-10-18T07:26:53.737 に答える