средство настройки частного поля в scala

#scala

#scala

Вопрос:

каков наилучший способ сделать поле класса в scala доступным только для чтения вне класса? я понимаю, что могу сделать что-то вроде этого:

 private var myvalX = 0 // default val
def myval = myvalX
def myval_=(x: Int) { myvalX = x }
  

но я нахожу это крайне некрасивым из-за оператора _= и того факта, что вам нужно определить отдельный параметр, имя которого отличается от методов. альтернативы были бы очень желательны. Спасибо!

Ответ №1:

Я не думаю, что это хорошая практика, когда частные поля и общедоступные имеют одно и то же имя. Например, вы написали

 private var myvalX = 0 // default val
def myval = myvalX
def myval_=(x: Int) { myvalX = x }
  

который вообще не делает myval доступным только для чтения! Вы, вероятно, имели в виду что-то вроде

 private def myval_=(x: Int) { myvalX = x }
  

который был бы доступен только для чтения. Но это прекрасный пример того, почему это плохая идея — вы напрашиваетесь на путаницу между общедоступным интерфейсом и вашими личными деталями реализации. Другие проблемы, которые могут возникнуть, заключаются в том, что пользователи не осознают, что значение может измениться из-за них, подклассы переопределяют общедоступный метод получения, не осознавая, что частный метод установки недоступен, и так далее.

Если вы не пытаетесь использовать общее имя, то становится яснее, что есть две вещи, о которых следует подумать: ваши базовые данные и общедоступный интерфейс, который полагается на эти данные.

 private var myData = 0
def data = myData
  

Это не так уж плохо, не так ли?

В качестве альтернативы, вы можете использовать различные приемы, чтобы все выглядело несколько приятнее, если вы действительно настаиваете на использовании этого шаблона. Например, если у вас есть несколько полей, вы могли бы

 class C {
  abstract class ReadOnly[A] { def value: A }
  private class ReadWrite[A](var value: A) extends ReadOnly[A]

  private implicit def access[A](ro: ReadOnly[A]) = ro.asInstanceOf[ReadWrite[A]]
  def rw[A](a: A): ReadOnly[A] = new ReadWrite(a)

  val data = rw(0)
  val comment = rw("Ho-hum")
}
  

который позволит любому объекту в классе C устанавливать data.value и comment.value , и только позволит всем остальным их читать. (Редактировать: изменено, чтобы включить все полезные элементы в исходный пример, поскольку, если вы их опустите, вы можете допустить ошибки.)