2010-05-12 2 views
6

В Scala я хотел бы написать абстрактный класс с абстрактным атрибутом path:Обход абстрактных атрибутов в Java

abstract class Base { 

    val path: String 

} 

class Sub extends Base { 

    override val path = "/demo/" 

} 

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

Мои идеи:

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

abstract class Base { 

    protected String path; 

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

} 

class Sub extends Base { 

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

} 

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

abstract class Base { // could be an interface too 

    abstract String getPath(); 

} 

class Sub extends Base { 

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

} 

Какой из них вам больше нравится? Другие идеи?

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

+0

Предупреждение: б) не скомпилируется. Вам нужно добавить модификатор «abstract» к абстрактному методу. – BalusC

+0

Связанный вопрос: http://stackoverflow.com/questions/2371025/abstract-variables-in-java – BalusC

+1

FYI: Scala работает на JVM, которая не поддерживает абстрактные поля, поэтому Scala в основном использует абстрактные методы внутри. – RoToRa

ответ

5

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

Рассмотрим следующий пример класса:

abstract class Test{ 
    val path: String 
} 

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

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

public abstract class Test extends java.lang.Object implements scala.ScalaObject{ 
    public abstract java.lang.String path(); 
    public Test(); 
} 
1

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

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

+0

Да, 'путь' доступен во время компиляции. Почему вы предпочитаете вариант b) если путь должен быть неизменным? – deamon

+0

Предоставление подкласса override 'getPath' представляется разумным, если путь можно вычислить по-разному. Будущий подкласс мог бы, например, захотеть прочитать путь из файла конфигурации, который изменяется во время выполнения или что-то еще, и тогда нет смысла иметь для него защищенную переменную. – aioobe

0

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

+1

Но компилятор не применял бы для вызова этого метода в подклассе, так что значение могло бы остаться неинициализированным. – deamon

0

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

1

эквивалент является В поскольку значения фиксируется.

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

0

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

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

Смежные вопросы