1

私は何日も暗黙の変換の問題に取り組んできましたが、どういうわけか私は自分が間違っていることを理解できません。暗黙の問題を扱うSOに関する他のすべての質問を読みましたが、問題が何であるかはまだわかりません。

例として、次のようなJavaインターフェースを考えてみましょう(簡潔にするためにTはObjectを拡張します)。

public interface JPersistable<T extends Object> {
    public T persist(T entity);
}

Scalaでは、次のことを行います。

case class A()
case class B() extends A
case class C()
case class D() extends C

trait Persistable[DTOType <: A, EntityType <: C] {
  // this would be implemented somewhere else
  private def doPersist(source: EntityType): EntityType = source

  // this does not implement the method from the Java interface
  private def realPersist(source: DTOType)(implicit view: DTOType => EntityType): EntityType = doPersist(source)

  // this DOES implement the method from the Java interface, however it throws:
  // error: No implicit view available from DTOType => EntityType.
  def persist(source: DTOType): EntityType = realPersist(source)
}

case class Persister() extends Persistable[B, D] with JPersistable[B]

object Mappings {
  implicit def BToD(source: B): D = D()
}

object Test {
  def main(args: Array[String]) {

    import Mappings._
    val persisted = Persister().persist(B())
  }
}

コメントで述べたように、コンパイル時に例外が発生します。私の質問は次のとおりです。

1)明示的に暗黙の変換を指定する必要があるのはなぜdoRealPersistですか?次のことを行っても、変換が行われることを期待していました。

trait Persistable[DTOType <: A, EntityType <: C] {
  // this would be implemented somewhere else
  private def doPersist(source: EntityType): EntityType = source

  def persist(source: DTOType): EntityType = doPersist(source)
}

ただし、これもコンパイルされません。

persist2)実際のメソッド呼び出し()ではなく、コンパイルが失敗するのはなぜval persisted = Persister().persist(B())ですか?これは、EntityTypeとDTOTypeの実際のタイプがわかっている最初の場所ですよね?

3)私が達成しようとしていることを行うためのより良い方法はありますか?繰り返しますが、これは私がやろうとしている実際のことではありませんが、十分に近いものです。

この質問が無知である場合は事前にお詫び申し上げます。ご協力いただきありがとうございます。

4

1 に答える 1

2

トレイト内で変換を利用できるようにする必要があります。暗黙の変換が必要なことを外部がpersist密かに要求していることを外部が知らないため、外部から暗黙的に渡すことはできません。realPersistこれは、考慮しなくてもすべて失敗しますJPersistable

たとえば、追加できます

implicit def view: DTOType => EntityType

トレイトのメソッドとして、それからコンパイルされます。(その後、ドロップすることrealPersistもできます。)

次に、そのビューセットを取得する方法が必要です。あなたはできる

case class Persister()(implicit val view: B => D) extends Persistable[B,D]

そして、あなたはすべて元気です。(は特性のをimplicit val満たします。)implicit def

しかし、今はもっと大きな問題があります。Javaインターフェースの署名がScalaの署名と一致していません。同等のScalaは

trait JPersistable[T <: Object] { def persist(t: T): T }

persist同じタイプを取得して返す方法をご覧ください。そして、それがあなたのScalaクラスにどのように含まれていないかを見てください。それはうまくいきませんし、そうすべきでもありません!したがって、ここで達成しようとしていることを正確に再考する必要があります。暗黙の変換を利用可能にしたいだけかもしれません-メソッドに渡さないでください!-そしてScalaに暗黙の変換を適用させて、からへのpersistマップがあると思うようにしますが、実際にはJavaインターフェースが必要とする変換。DTOTypeEntityTypeEntityTypeEntityType


編集:たとえば、標準の暗黙的な変換を使用して投稿したものの作業バージョンは次のとおりです。

trait JPer[T] { def persist(t: T): T }
class A
case class B() extends A
class C
case class D() extends C
trait Per[Y <: C] extends JPer[Y] {
  private def doIt(y: Y): Y = y
  def persist(y: Y) = doIt(y)
}
case class Perer() extends Per[D] // "with JPer" wouldn't add anything!
object Maps { implicit def BtoD(b: B): D = D() }
object Test extends App {
  import Maps._
  val persisted = Perer().persist(B())
}

どのタイプがどこで使用されているかに注意してください!(誰がB、誰がD、どの方向に変換する必要がありますか?)

于 2012-05-11T22:27:28.497 に答える