Я ищу способ ограничить вызовы определенных объектов.Учитывая транзакционную систему, которая определяет ссылочный тип, тип транзакции и идентификатор:
trait Sys[S <: Sys[S]] {
type Ref[A]
type Tx <: Txn[S]
type ID
}
Я хотел бы иметь возможность смешивать черты, которые можно использовать для создания изменяемых ссылок:
trait Mutable[S <: Sys[S]] {
def id: S#ID
protected final def newRef[A](implicit tx: S#Tx): S#Ref[A] =
tx.newRef[A](this)
}
И фабрика ссылок определяется как часть транзакции:
trait Txn[S <: Sys[S]] {
/* private[Mutable] */ def newRef[A](mut: Mutable[S]): S#Ref[A]
def newID: S#ID
}
Теперь проблема заключается в том, что в следующей структуре я могу создавать ссылки с ложным контекстом:
def newStruct[S <: Sys[S]](cross: Mutable[S])(implicit tx: S#Tx) =
new Mutable[S] {
val id = tx.newID
val allowed = newRef[Int]
val forbidden = tx.newRef[Int](cross) // shouldn't compile...
}
Я бы хотел запретить последний звонок.Очевидно, что я не могу сделать newRef
в Txn
закрытым для Mutable
, потому что Mutable
не является включающим классом Txn
.Я также хотел бы не использовать конфиденциальность пакета, поскольку можно легко взломать newRef
, определив объект в этом пакете.
В идеале мне бы хотелось:
trait Sys[S <: Sys[S]] { trait Mutable }
class MyStruct[S <: Sys[S]] extends S#Mutable { ... }
, чторешить все проблемы.Но это запрещено, поскольку S
в S#Mutable
"is not a legal prefix for a constructor"
во вселенной скалака ...
Спасибо за предложения!