Неизменность с наследованием шаблона проектирования - PullRequest
0 голосов
/ 15 мая 2018

Я реализую некоторый код в Scala, следуя инструкциям на Java.

В руководстве есть фрагмент кода, который можно свернуть следующим образом:

public abstract class A {
    private int id;

    public A(String name) {
        id = Helper.getId(name);
        fetchAllAttributes();
    }

    protected abstract void fetchAllAttributes();

    protected int fetchAttribute(String attribute) {
        Helper.getAttribute(id, attribute);
    }

    public class B extends A {
        int volume;

        public B() {
            super("B");
        }

        @Override
        protected void fetchAllAttributes() {
            volume = super.fetchAttribute("volume");
        }

    }
}

И этоВот как это выглядит, когда вы переводите его в Scala:

abstract class A(val name: String) {
  private val id = Helper.getId(name)
  fetchAllAttributes()

  protected def fetchAllAttributes(): Unit

  protected def fetchAttribute(attribute: String): Int = {
    Helper.getAttribute(id, attribute)
  }

  class B() extends A("B") {
    var volume = 0

    override protected def fetchAllAttributes(): Unit = {
      volume = super.fetchAttribute("volume")
    }
  }

}

И здесь я хотел бы задать два вопроса:

  1. Есть ли название для этого шаблона, гдеВы вызываете абстрактный метод в конструкторе абстрактного класса и предоставляете метод для использования дочерними классами в их реализации?
  2. Как разработчик Scala, мне действительно не нравятся изменяемые объекты и переменные.Есть ли хороший способ реализовать это неизменным образом, используя только val s?

Ответы [ 2 ]

0 голосов
/ 15 мая 2018
  1. Вы можете назвать это анти-паттерном.См. предыдущие обсуждения о SO о вызове переопределяемых методов из конструктора.
  2. При рефакторинге кода Java в код Scala, то, что мне больше всего помогло вначале, это понимание методов с побочными эффектами.Вы не хотите иметь методы в классах, которые зависят от изменяемых полей и / или меняют их. (Как у вашего класса B с этим томом) Этот небольшой принцип помогает сохранить классы чистыми от изменяемого состояния.Это не правило, которое установлено в камень, хотя.Например, для актеров Акка нередко бывает изменчивое состояние.

Цитата из руководства по scala ( Источник ):

Опять же, это означает, что функция не должна иметь побочных эффектов.Он должен принимать входные переменные, не изменять эти переменные, а затем вычислять и возвращать что-то новое.В отличие от объектно-ориентированного программирования, вы не должны изменять (изменять) состояние других переменных, даже если эти переменные являются (а) переменными вашего класса или (б) переменными, которые были переданы вашей функции / методу.

0 голосов
/ 15 мая 2018

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

class FactoryFromAttributes[A](name: String) {
  def construct(f: (String => Int) => A): A = {
    val id = Helper.getId(name)
    f(str => Helper.getAttribute(id, str))
  }
}

class B(volume: Int)

object B extends FactoryFromAttributes[B]("B") {
  def apply(): B = construct { fetchAttribute =>
    new B(fetchAttribute("volume"))
  }
}

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

...