В scala довольно легко переопределить методы доступа и мутаторы по умолчанию; это заставляет меня чувствовать себя намного более комфортно с публичными атрибутами, потому что это позволяет мне изменить поведение доступа в более позднее время без изменения подписи моего класса. Вот как это делается:
class Topic {
var tags = "default";
}
становится:
class Topic{
private var _tags = "default";
def tags = {
_tags
}
def tags_ =(s:String){
_tags = s
}
}
Однако это не устраняет основную причину создания закрытых полей; он не позволяет изменять поведение элемента компонента. Например, с Growable я могу захотеть сделать что-то особенное, добавив новый элемент или очистив свой список. Один из способов приблизиться к этому — создать класс, реализующий Growable, например:
class Topic {
private var _tags:Growable[String] = new MyMutableList[String]()
def tags = {
_tags
}
def tags_=(Growable[String]){
_tags = m
}
}
class MyMutableList[T] extends MutableList[T](){
override def +=(t:T) {
println("adding: " + t.toString())
super.+=(t)
}
override def clear() {
println("clearing")
super.clear()
}
}
Однако это не решает проблему полностью, потому что «теги» по-прежнему могут быть установлены равными любому Growable[String]. Это изменит поведение метода clear() на поведение любого предоставленного типа.
Можно ли каким-либо образом переопределить метод атрибута так же, как можно переопределить метод доступа/мутатор атрибута? Это не компилируется, но выражает то, что я пытаюсь сделать:
class Topic {
private var _tags:Growable[String] = new MutableList[String]();
def tags = {
_tags
}
def tags_=(m:Growable[String]){
_tags = m
}
def tags_.+=(s:String) {
println("adding: " + t.toString())
_tags += s
}
def tags_.clear(){
println("clearing")
_tags.clear()
}
}