3

我有一组在类层次结构中管理数据库存储的类,如下所述,并且希望案例类能够访问伴随对象的父类中的受保护方法:

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 的调用是非法的,因为 User(类)不在 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 类型的函数移动到单例中,这使得调用代码相当冗长,要么复制方法签名。

4

2 回答 2

1

我刚刚意识到一个可能的解决方案是将 User 和 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 上进行公共“插入”,最好不要让它导致部分受保护的重载)。

于 2012-09-06T16:02:27.107 回答
0

您可以将接口作为特征 CrudOps[T] 提供,从它派生另一个受保护的特征 TableBase[T] 并提供实现,并从 TableBase[T] 派生单例对象。这样 TableBase 在编译单元之外是不可见的,但客户端可以安全地使用 CrudOps[T]。

于 2012-09-06T15:11:15.113 回答