1

更新:私は答えを受け入れましたが、なぜ私が試したことが機能しないのか(Scalaの暗黙的な動作を理解するために)、まだ非常に興味があります。他の回答は大歓迎です。

(Circumflex についてあまり知識がなくてもこの質問に答えられることを願っていますが、念ため、文書化されたソース コード リファレンスを次に示します。)

Circumflex ORMライブラリにいくつかの便利な関数を追加しようとしていますが、Scala の暗黙的な変換を使用しようとすると、いくつかの障壁に遭遇します。以下、暗黙の変換がトリガーされないのはなぜですか? サブクラス化および/または再帰型パラメーターとの複雑な相互作用があると思われます。

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

1 に答える 1

4

率直に言って、私は暗黙のパラメーターを使用したことがなく、それらを使用せざるを得ない状況に遭遇したこともありません (Circumflex 自体は暗黙のパラメーターなしで記述されており、私が懸念している限りではうまくいきます)。

とにかく、私はあなたのシナリオを再現して機能させることができました。ただし、すべてがうまくいくには 2 つの暗黙的な処理が必要でした。コードは次のとおりです。

// 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]

それが役に立てば幸い。

于 2011-11-08T09:40:10.283 に答える