2012-09-06 3 views
2

У меня есть набор классов, которые управляют хранилищем db в иерархии классов, как описано ниже, и хотел бы, чтобы класс case мог получить доступ к защищенным методам в родительском классе объекта сопутствующего :Scala: Использование защищенных методов родительского объекта

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.update в User.changeEmail является незаконным, так как пользователь (класс) не находится в цепочке наследования от 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, что делает код вызова довольно многословным, либо дублирует сигнатуры метода.

+1

Объявляет методы ['private' или' protected' на уровне пакета] (http://www.artima.com/pins1ed/packages-and-imports.html#lst:access-qualifiers) вариант ? – DaoWen

+0

Теоретически, да. Это потребует довольно много перекодировки - TableBase находится в отдельном проекте с символическим источником, используемом несколькими другими проектами, поэтому искажение пространства пакета будет бесполезным. – Jxtps

ответ

1

Я просто понял, что возможное решение переключить «на-а» к «имеет-а» отношения между Пользователем и TableBase, например, так:

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(...) 
} 

Я хотел, чтобы иметь возможность настроить некоторые аспекты TableBase внутри пользователя, но это на самом деле все еще возможно и довольно легко, выполнив:

object User { 
    private val db = new TableBase[User] { 
    // Override stuff here 
    } 
} 

на самом деле, это гораздо лучшее решение, чем то, что я изначально имел и избежать конфликтов именования по методам (т.е. есть основания, чтобы иметь публичная «вставка» на пользователя, и приятно не h а это приводит к частично защищенной перегрузке).

+0

Я пробовал это и был недоволен результатом - в конце концов было несколько произвольно, какая функциональность будет идти в TableBase (и тем самым будет скрыта) и что будет доступным извне. Закончилось просто, чтобы содержимое TableBase было общедоступным. В более четком сценарии это подход, который я бы взял. – Jxtps

0

Вы можете предоставить интерфейс как черта CrudOps [T], есть еще защищены черта TableBase [T] извлечь из него и обеспечить реализацию, и вывести одноплодной объект из TableBase [T]. Таким образом, TableBase не отображается вне модуля компиляции, но клиенты могут безопасно потреблять CrudOps [T].

+0

Я, вероятно, что-то пропустил - я хочу, чтобы методы в TableBase/CrudOps вызывались только внутри класса пользователя и singleton, а не извне - если клиенты могут «потреблять» CrudOps, тогда обновление/вставка/etc можно вызывать извне? (обратите внимание, что файлы на самом деле не находятся в одном и том же пакете или исходном файле) – Jxtps

+0

А, я вижу, это упростит - просто создайте защищенный пакет TableBase. Например, если ваш пакет com.example.crud, вы захотите объявить защищенный [crud] TableBase [T] ... –

+0

См. Мой [комментарий] (http://stackoverflow.com/questions/12291566/scala -using-companion-objects-parents-protected-methods/12303133 # comment16508186_12291566) на вопрос о защите пакета TableBase. – Jxtps

Смежные вопросы