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

但是,这也不能编译。

2) 为什么编译在persist实际的方法调用 () 处而不是在实际的方法调用处失败val persisted = Persister().persist(B())?那应该是第一个知道 EntityType 和 DTOType 的实际类型的地方,对吧?

3)有没有更好的方法来做我想要实现的目标?同样,这不是我想要做的实际事情,但足够接近。

如果这个问题是无知的,请提前道歉,并提前非常感谢您的帮助。

4

1 回答 1

2

您需要在 trait中提供转换。您不能从外部隐式传递它,因为外部不知道需要隐式转换的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映射 from DTOTypeto EntityType,但你真的只有EntityType转换EntityTypeJava接口所需的。


编辑:例如,这是您使用标准隐式转换发布的工作版本:

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 回答