2011-11-08 61 views
1

更新:我已经接受了一个答案,但我仍然非常好奇,为什么我尝试不起作用(了解Scala隐式行为)。任何其他答案将不胜感激。为什么不是这个Scala隐式转换工作?

(希望这个问题是没有回旋的很多知识回答的,但为了以防万一,here's的记录源代码参考。)

我试图在Circumflex ORM库添加了一些方便的功能,但我m遇到了一些试图使用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) 
} 
+0

不确定它会在这种情况下有所帮助,但一般建议指定隐式转换的返回类型。另外,回答'new {def GET(f:RelationNode [PK,R] => Predicate)= 0}'是什么类型的问题可以帮助您解决问题。 – Jamil

+0

@Jamil明确指定返回类型并将匿名类提升到指定类中没有任何区别。 – Yang

+0

这是否真的是证明问题所需的最低代码? –

回答

4

坦率地说,我从来没有使用隐含参数,我从来没有见过这迫使我使用他们的条件(抑扬本身是用无隐含参数,去得很好,据我而言)。

无论如何,我已经能够重现您的方案并使其工作。然而,它让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] 

希望它有帮助。

+0

我想我主要好奇为什么两个implicits是必要的,为什么原来不工作。我会标记这个答案被接受,但我很想听到任何其他的答案/见解! – Yang

相关问题