【问题标题】:Understanding the interaction in Scala between self-types and type bounds理解 Scala 中自身类型和类型边界之间的交互
【发布时间】:2011-07-27 19:19:34
【问题描述】:

我之前尝试将这个问题分解为更小、更简单的问题herehere,但我意识到这些问题的答案虽然在技术上是正确的,但并不能帮助我理解这个特殊情况。

我正在使用一个库 Circumflex ORM,它允许您按如下方式定义模式:

class User extends Record[Int, User] {
  val name = "name".TEXT
  val age = "age".INTEGER
  def relation = User
}
object User extends User with Table[Int, User]

这是因为 Record 范围内的隐式视图:

abstract class Record[PK, R <: Record[PK, R]] extends Equals { this: R =>
  implicit def view(x: String) = new DefinitionHelper(x, this)
  ...
}

class DefinitionHelper[R <: Record[_, R]](name: String, record: R) {
  def TEXT = ...
  def INTEGER = ...
  ...
}

我正在尝试在 TEXT 等之外引入一种新的扩展方法,称为 BYTEA。所以我知道我需要自己的隐式帮助类:

class DefinitionHelper[R <: Record[_, R]](name: String, record: R) {
 def BYTEA = new BytesField[R](name, record)
}

现在,每当我定义新记录时,我都需要一个隐式范围,但是 不想每次都写import语句:

class User extends Record[Int, User] {
 import Implicits._
 ...
}

而且我不想将这个隐式引入任何其他范围 除了记录定义。

import Implicits._
class User extends Record[Int, User] { ... }

所以一个想法是继承 Record (或引入一个 mixin),然后定义 通过扩展 MyRecord 而不是 Record(或始终 在 MyMixin 中混合)。

class User extends MyRecord[Int, User] { ... }

我第一次尝试:

abstract class MyRecord[PK, R <: MyRecord[PK, R]]
extends Record[PK, R] {
  implicit def str2ddlHelper2(str: String) =
    new DefinitionHelper(str, this)
}

这会产生:

illegal inheritance;  self-type MyRecord[PK,R] does not conform to ru.circumflex.orm.Record[PK,R]'s selftype R

所以我尝试了:

abstract class MyRecord[PK, R <: MyRecord[PK, R]]
extends Record[PK, MyRecord[PK, R]] {
 implicit def str2ddlHelper2(str: String) =
   new DefinitionHelper(str, this)
}

但是在定义记录时我遇到了这两个问题:

class User extends MyRecord[Int, User] {
 val id = "id".INTEGER
 val value = "value".BYTEA // works
 val value2 = new DefinitionHelper("", this) // does not work?!
 ...
 def relation = User // another error here
}
object User extends User with Table[Int, User]

错误是:

inferred type arguments [User] do not
conform to class DefinitionHelper's type parameter bounds [R <:
ru.circumflex.orm.Record[_, R]]

type mismatch;  found   : User.type (with
underlying type object User)  required:
ru.circumflex.orm.Relation[Int,MyRecord[Int,User]]
Note: User <:
MyRecord[Int,User] (and
User.type <:
ru.circumflex.orm.Table[Int,User]), but
trait Relation is invariant in type R. You may wish to define R as +R
instead. (SLS 4.5)

经过更多的摆弄,我发现一些有用的东西让我自己感到惊讶:

abstract class MyRecord[PK, R <: MyRecord[PK, R]]
extends Record[PK, R] { this: R =>
  implicit def str2ddlHelper2(str: String) =
    new DefinitionHelper(str, this)
}

我很想了解这里刚刚发生的事情,也许还有一些例子可以帮助我更好地理解事情,这样我就不会觉得我总是“摆弄直到它起作用” 。”

为问题标题道歉 - 不确定它是否有意义。

【问题讨论】:

    标签: scala circumflex-orm


    【解决方案1】:

    您的第一个错误比较简单,并且可以通过您的最终解决方案轻松解决。声明中的self类型R=&gt;

    Record[PK, R <: Record[PK, R]] extends Equals { this: R =>
    

    强制Record 的每个后代确保它也是一个 R(它不会使它成为一个 R,后代必须做一些事情才能成为一个 R)。在实践中,这意味着在class X extends Record[PK, R] 中,R 必须是X 的祖先(因为还有R &lt;: Record[PK, R],所以大多数时候它应该是X,但正如我们将在最后,情况可能并非如此)。

    此约束在 MyRecord 中消失,因此您的第一个错误。您的最终解决方案再次说明了约束,这就是它的结束。


    您的第二个版本更复杂。 我将从第二个错误开始。

    首先,来自 Circumflex API 的一些元素没有在上面说明。

    • Record 有一个摘要 def relation: Relation[PK, R]
    • Table[K,R] 扩展 Relation[K,R]

    您将User 类中的关系定义为对象User,它是Table[Int, User],因此是Relation[Int, User]

    但是,您的课程 UserMyRecord[Int, User],但这意味着它是 Record[Int, MyRecord[Int, User]],而不是 Record[Int, User]RecordR (这里很重要)是 MyRecord[Int, User],而不是 User。因此关系必须是Relation[Int, MyRecord[Int, User]]

    Relation[Int, User] 不是Relation[Int, MyRecord[Int, User]],即使UserMyRecord[Int, User]。通常,如果BA,则C[B] 不是C[A],除非类C 声明为C[+X] 而不是C[X]。 (因此,关于Relation 的消息是invariant(没有+),并建议+R 使其在R协变)。

    我真的不太确定 DefinitionHelper 中的错误。这似乎与 R 再次成为 MyRecord[Int, User] 有关。如果您将其明确声明为泛型参数R,则这样做

    new DefinitionHelper[MyRecord[Int, User]]("", this) 
    

    它应该可以工作(我在一个非常接近您的代码的示例中做到了,但实际上并未使用抑扬符)。为什么编译器不推断,我不知道。无论如何,您的User 不是Record[Int, User] 而是Record[Int, MyRecord[Int, User]] 这一事实必然会导致问题。实际的解决方案要简单得多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-24
      • 2021-01-24
      • 2013-05-31
      • 2022-12-09
      • 1970-01-01
      相关资源
      最近更新 更多