Обход абстрактных атрибутов в Java - PullRequest
6 голосов
/ 12 мая 2010

В 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 ]

5 голосов
/ 12 мая 2010

То, что делает 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();
}
1 голос
/ 12 мая 2010

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

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

1 голос
/ 12 мая 2010

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

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

0 голосов
/ 14 мая 2010

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

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

0 голосов
/ 12 мая 2010

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

0 голосов
/ 12 мая 2010

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

...