Обходное решение для абстрактных атрибутов в Java

В Scala я записал бы абстрактный класс с абстрактным атрибутом path:

abstract class Base {

    val path: String

}

class Sub extends Base {

    override val path = "/demo/"

}

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

Мои идеи:

a) параметр конструктора

abstract class Base {

  protected String path;

  protected Base(String path) {
    this.path = path;
  }

}

class Sub extends Base {

    public Sub() {
        super("/demo/");
    }

}

b) абстрактный метод

abstract class Base { // could be an interface too

  abstract String getPath();

}

class Sub extends Base {

    public String getPath() {
        return "/demo/";
    }

}

Какой Вы любите лучше? Другие идеи?

Я склонен использовать конструктора, так как значение пути не должно быть вычислено во времени выполнения.

6
задан deamon 12 May 2010 в 15:19
поделиться

6 ответов

То, что Scala делает внутренне, вы описываете как метод B.

Возьмем следующий пример класса:

abstract class Test{
    val path: String
}

Когда вы компилируете это с помощью scalac, он сгенерирует абстрактный класс Java с абстрактным методом с именем attr, который возвращает String. Причина, по которой это может произойти, заключается в том, что val является постоянным и поэтому может эмулироваться только геттером, а не сеттером. Поэтому, если вы хотите получить доступ к этому классу из Java, вы можете просто переопределить абстрактный метод получения.

Это эквивалент класса Java, который будет создан (вывод javap):

public abstract class Test extends java.lang.Object implements scala.ScalaObject{
    public abstract java.lang.String path();
    public Test();
}
5
ответ дан 17 December 2019 в 00:05
поделиться

Я бы выбрал вариант b, потому что если по какой-либо причине путь зависит от других атрибутов, то устанавливать атрибут в суперклассе каждый раз, когда изменяется другой атрибут. Если вам нужно реализовать геттер, тогда нет проблем. Я не могу придумать ни одного конкретного случая, когда вариант а был бы более применим .

0
ответ дан 17 December 2019 в 00:05
поделиться

Если путь никогда не изменится, я бы выбрал вариант а, в противном случае я бы выбрал вариант б.

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

1
ответ дан 17 December 2019 в 00:05
поделиться

Эквивалент B , поскольку значения фиксированы.

Опция A получает путь в конструкторе, и это значение может быть вычислено во время выполнения, что не соответствует классу Sub в примере scala.

1
ответ дан 17 December 2019 в 00:05
поделиться

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

0
ответ дан 17 December 2019 в 00:05
поделиться

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

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

0
ответ дан 17 December 2019 в 00:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: