#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
, и только позволит всем остальным их читать. (Редактировать: изменено, чтобы включить все полезные элементы в исходный пример, поскольку, если вы их опустите, вы можете допустить ошибки.)