Ранее я пытался разбить эту проблему на более мелкие, более простые проблемы здесь и здесь , но я понял, что ответы на них, хотя и технически правильные, не помогают мне понять эту конкретную проблемуcase.
Я использую библиотеку 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]
Это работает из-за неявного представления, которое находится в-scope в 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)
}
Теперь мне нужен неявный в области действия всякий раз, когда я определяю новые записи, но я не хочу писать оператор импорта каждый раз:
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)
}
Мне любопытно понять, что только что произошло здесь, а также, возможно, еще несколько примеров, которые помогут мне лучше обернуть голову вокруг вещейтак что я не чувствую, что я всегда "возиться доэто работает. "
Извините за заголовок вопроса - не уверен, что это имеет какой-либо смысл.