简体   繁体   English

为什么这个Scala隐式转换不起作用?

[英]Why isn't this Scala implicit conversion working?

Update : I've accepted an answer but I'm still very curious why what I tried doesn't work (to understand Scala implicit behaviors). 更新 :我已经接受了答案,但我仍然很好奇为什么我尝试的不起作用(了解Scala隐式行为)。 Any other answers would be greatly appreciated. 任何其他答案将不胜感激。

(Hopefully this question is answerable without much knowledge of Circumflex, but just in case, here's the documented source code reference.) (希望这个问题在没有Circumflex知识的情况下是可以回答的,但是以防万一, 这里是文档化的源代码参考。)

I'm trying to add some convenience functions over the Circumflex ORM library, but I'm running into some barriers trying to use Scala implicit conversions. 我正在尝试在Circumflex ORM库上添加一些便利功能,但是我遇到了一些尝试使用Scala隐式转换的障碍。 Below, why doesn't the implicit conversion trigger? 下面,为什么隐式转换不会触发? I suspect there's some complex interaction with the subclassing and/or the recursive type parameters. 我怀疑与子类和/或递归类型参数有一些复杂的交互。

import ru.circumflex.orm._

// I subclass Record and Table to add my own convenience methods etc. (not pasted, irrelevant)
abstract class XRecord[PK, R <: XRecord[PK, R]] extends Record[PK, R] { this: R => }
trait XTable[PK, R <: XRecord[PK, R]] extends Table[PK, R] { this: R => }

// Example entity.
class Org extends XRecord[Long,Org] {
  val id = "id".BIGINT.NOT_NULL.AUTO_INCREMENT
  def PRIMARY_KEY = id
  def relation = Org
}
object Org extends Org with XTable[Long,Org]

object Test extends App {
  // I want this conversion to work for all Records, not just XRecords.
  // Need implicit f to be able to accept XRecord, a subclass of Record.
  implicit def toRichRelationNode[PK, R <: Record[PK,R], RR](xs: RR)(implicit f: RR => RelationNode[PK,R]) =
    new { def GET(f: RelationNode[PK,R] => Predicate) = 0 }

  // This works.
  toRichRelationNode(Org) GET (_.id EQ 1)

  // This doesn't:
  // "No implicit view available from Org.type => ru.circumflex.orm.RelationNode[PK,R]."
  Org GET (_.id EQ 1)
}

Frankly, I've never used implicit parameters and I've never met a condition which forced me to use them (Circumflex itself is written without implicit parameters and goes pretty well as far as I am concerned). 坦率地说,我从来没有使用过隐式参数,而且我从未遇到过强迫我使用它们的条件(Circumflex本身是在没有隐式参数的情况下编写的,就我而言非常好)。

Anyhow, I've been able to reproduce your scenario and make it work. 无论如何,我已经能够重现你的场景并使它工作。 It took 2 implicits, however, to make everything go fine. 然而,为了让一切顺利,需要花费两个时间。 Here's the code: 这是代码:

// The helper which holds custom methods, it will accept any subclass of R
class NodeHelper[PK, R <: Record[PK, R]](val node: RelationNode[PK, R]) {
  def GET(f: R => Predicate): Option[R] = node.criteria.add(f(node)).unique()
} 

// Now the implicits and usage scenario

object Tester {

  implicit def nodeToHelper[PK, R <: Record[PK, R]](node: RelationNode[PK, R]): NodeHelper[PK, R] = new NodeHelper(node)

  implicit def tableToHelper[PK, R <: Record[PK, R]](table: Table[PK, R]): NodeHelper[PK, R] = new NodeHelper(table.AS("this"))

  // Testing with table
  println(User GET (_.cn EQ "patrick"))
  // Testing with node
  println(User.AS("u") GET (_.cn EQ "patrick"))
}

// And finally, the test model we've mentioned above

class User extends Record[Long, User] {
  def PRIMARY_KEY = id
  val id = "id".BIGINT.NOT_NULL.AUTO_INCREMENT
  val cn = "cn".TEXT.NOT_NULL
  def relation = User
}

object User extends User with Table[Long, User]

Hope it helps. 希望能帮助到你。

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

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