Переопределить методы атрибута в scala

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

person cscan    schedule 17.06.2015    source источник


Ответы (1)


Вы не можете переопределить методы атрибута в классе.

  • Вы можете ограничить тип вашего атрибута tags, чтобы сделать невозможным установку атрибута tags на другой Growable[String}.
  • Вы также можете опустить метод мутатора и добавить методы addTag(tag: String): Unit и cleanTags : Unit.
person Peter Neyens    schedule 17.06.2015
comment
Два других подхода, которые приходят мне на ум: 1. Вы можете обернуть m в сеттер (или геттер, как набросал cscan) и заставить объект-оболочку (делегата) переопределить clear и +=. 2. Вы можете использовать отражение, чтобы переопределить методы экземпляра tags. Последнее, вероятно, ближе всего к тому, что задает вопрос. Однако, принимая во внимание хорошие методы проектирования, ваш второй пункт — это путь. - person Kulu Limpa; 18.06.2015