Что я делаю неправильно?(С параметрами суперкласса Scala) - PullRequest
1 голос
/ 08 августа 2011

У меня есть родительский класс и несколько дочерних классов. Я хочу, чтобы при вызове определенных методов установки для экземпляров дочерних классов логическое значение «синхронизируется» в родительском классе было установлено на false. Должно быть возможным создание дочерних классов в синхронизированном или несинхронизированном состоянии.

Вот что я придумал:

class A(protected var isSync: Boolean) {
}
class B(var value:String, isSync: Boolean) extends A(isSync) {
  override def value_=(value:String): Unit = {
    this.isSync = false
    this.value = value
  }
}

Теперь, это не компилируется по ряду причин: присвоение value для this.value является неоднозначным; аннотация var уже определяет value_=; this.isSync ссылается на локальное поле конструктора isSync вместо родительского поля (доступного для записи).

В этом вопросе о переполнении стека указывалось, что я должен использовать __value (или любое имя, отличное от value) в качестве private var в конструкторе и сам определять сеттер. После еще нескольких попыток я разработал следующий код, который компилируется и работает:

class A(protected var isSync: Boolean) {
}
class B(private var __value: String, private val __isSync: Boolean)
    extends A(__isSync) {
  def value = __value
  def value_=(value: String) = {
    this.isSync  = false
    this.__value = value
  }
}

Однако этот код кажется настолько прогорклым, что к настоящему времени я подозреваю, что совершаю (если не больше) фундаментальную ошибку Может ли кто-нибудь поправить меня?

Таким образом, конкретные вопросы:

  1. Есть ли (и если какие) фундаментальные недостатки в том, что я пытаюсь реализовать? Для некоторого контекста: объекты, при изменении, могут (и, вероятно, должны) быть синхронизированы с сервером.
  2. Как правильно / лучше всего передать параметры в класс, который вы расширяете?
  3. Какой правильный / лучший способ переопределить установщик, сгенерированный var (или вообще предоставить собственную реализацию сеттера)?

1 Ответ

3 голосов
/ 08 августа 2011

О вопросе 1: Полагаю, вы хотите отследить, был ли объект изменен с момента последнего копирования на сервер, не так ли? Это разумно, поскольку копия на сервере не может быть изменена: в противном случае обеспечение согласованности реплики является более сложным (согласованность реплики является ключевым словом для поиска в Google, но я бы не рекомендовал его). Для ясности я бы говорил о том, чтобы быть чистым или грязным - синхронизация слишком напоминает мне оператор synchronized Java.

Что касается вопроса 2, вам не нужно указывать __isSync a private val (который будет храниться в классе), вы можете оставить его в качестве параметра конструктора. Пока он не используется (кроме вызова конструктора A), __isSync не должен занимать дополнительное место в экземплярах B. Я удалил там аннотацию private val, получив этот код, который правильно компилируется, как и ожидалось.

class A(protected var isSync: Boolean) {
}
class B(private var __value: String, __isSync: Boolean)
    extends A(__isSync) {
  def value = __value
  def value_=(value: String) = {
    this.isSync  = false
    this.__value = value
  }
}

Об эстетике и вопросе 3: я бы просто избежал двойного подчеркивания. Подобные примеры из программирования в Scala (раздел 18.2) просто используют более короткие имена. Они также используют private[this] для предотвращения доступа к члену из других экземпляров того же класса. Наконец, вы можете удалить {} после класса decl. в этом примере (даже если возможно не в вашем коде).

Таким образом, мы получили бы код, подобный этому, что близко к примерам, которые я уже упоминал:

class A(protected var isSync: Boolean)
class B(private[this] var v: String, sync: Boolean)
    extends A(sync) {
  def value = v
  def value_=(value: String) = {
    isSync  = false
    v = value
  }
}
...