我有一组类,它们在如下所述的类层次结构中管理数据库存储,并且希望case类能够访问伴随对象的父类中的受保护方法:
class TableBase[T] {
protected def insert(...):T {...}
protected def update(...) {...}
// Other "raw" CRUD-methods that I don't want the
// world to have access to
}
object User extends TableBase[User] {
}
case class User(id:Int, email:String) {
// But here it would be really useful to access the "raw" CRUD methods:
def changeEmail(newEmail:String) = User.update(...)
}
唯一的问题是User.changeEmail中对User.update的调用是非法的,因为用户(类)不在TableBase:的继承链中
method update in class TableBase cannot be accessed in object models.User
Access to protected method update not permitted because enclosing class
class User in package models is not a subclass of class TableBase in package
models where target is defined
有没有一种(方便的)方式可以允许这种类型的呼叫?
现在,我必须将changeEmail类型的函数移到singleton中,这使得调用代码相当冗长,或者复制方法签名。
我刚刚意识到,一个可能的解决方案是将用户和TableBase之间的"is-a"关系切换为"has-a"关系,如下所示:
class TableBase[T] {
def insert(...):T {...}
def update(...) {...}
}
object User {
private val db = new TableBase[User]
}
case class User(id:Int, email:String) {
def changeEmail(newEmail:String) = User.db.update(...)
}
我想能够在User中自定义TableBase的某些方面,但这实际上仍然是可能的,而且很容易做到:
object User {
private val db = new TableBase[User] {
// Override stuff here
}
}
事实上,这是一个比我最初拥有的要好得多的解决方案,并且避免了方法上的命名冲突(即,有理由在User上有一个公共"插入",并且很高兴没有导致部分受保护的重载)。
您可以将接口提供为trait CrudOps[T],从中派生另一个受保护的trait TableBase[T]并提供实现,并从TableBase[T].派生singleton对象。这样一来,TableBase在编译单元之外是不可见的,但客户端可以安全地使用CrudOps[T]。