Почему не работает неявное преобразование Scala? - PullRequest
1 голос
/ 08 ноября 2011

Обновление : я принял ответ, но мне все еще очень любопытно, почему то, что я попробовал, не работает (чтобы понять скрытое поведение 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)
}

1 Ответ

4 голосов
/ 08 ноября 2011

Честно говоря, я никогда не использовал неявные параметры и никогда не встречал условия, которые заставляли бы меня их использовать (сам 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]

Надеюсь, это поможет.

...