Статические методы в абстрактном классе - PullRequest
3 голосов
/ 01 июля 2011

Я хочу определить абстрактный метод следующим образом:

public abstract class Saveable {
    public Set<Field> getFieldSet();
    ...
}

getFields() всегда должен возвращать один и тот же вывод независимо от состояния объекта.Однако я не могу объявить это как статический метод, потому что я хочу, чтобы он был переопределен.Сейчас я реализую класс User, который расширяет Saveable, и у него есть несколько статических методов, которые требуют набора полей.Очевидно, я не могу получить это, потому что у меня нет объекта.Любая идея дизайна, которая позволила бы мне получить поля в статическом методе?

Ответы [ 6 ]

4 голосов
/ 01 июля 2011

Одним из подходов было бы «подделать» ссылку this, передав экземпляр правильного объекта статическим методам, а затем вызвав getFields для этого объекта.

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

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

1 голос
/ 01 июля 2011

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

public class User extends Savable {

    public static Set<AField> aSet = new HashSet<AField>();

    @Override
    public Set<? extends Field> getFields() {
        return aSet;
    }
}
1 голос
/ 01 июля 2011

К сожалению, унаследованный класс не может переопределить статический метод, но он может скрыть его, объявив статический метод с той же сигнатурой.

Это не поможет вам, если ваша конечная цель - использовать GetFields() внутри другого унаследованного метода в классе Saveable, потому что он всегда будет вызывать Saveable.getFields(), а не статический метод в вашем классе расширения.

0 голосов
/ 01 июля 2011

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

public abstract class Saveable {
    public static Set<? extends Field> getFields(Class<? extends Saveable> clazz) {
        return FieldsProvider.get(clazz);
    }
}

public class FieldsProvider {
    private static final Map<Class<? extends Saveable>, Set<? extends Field>> map =
        new HashMap<Class<? extends Saveable>, Set<? extends Field>>();

public static void registerFields(Class<? extends Saveable> clazz, Collection<? extends Field> col) {
    Set<? extends Saveable> set = new HashSet<? extends Saveable>();
    set.addAll(col);
    map.put(clazz, set);
}

public static Set<? extends Field> getFieldSet(Class<? extends Saveable> clazz) {
    Set<? extends Field> set = map.get(clazz);
    if (set != null) {
        return set;
    }
    return Collections.emptySet();
}
}

public class User extends Saveable {
static {
    FieldsProvider.registerFields(User.class, new HashSet<? extends Field>... ;
}

static void someMethod() {
    Set<? extends Field> fieldsSet = getFields(User.class);
    ...
}
}
0 голосов
/ 01 июля 2011

Расширяя ответ @dlev, как насчет того, чтобы сохранить поля в хэш-карте, отключенной уникальным идентификатором для класса.

Если вы используете Spring, вы можете внедрить набор полей в каждый объект.Следовательно, будет скопирована только ссылка.

0 голосов
/ 01 июля 2011

При вызове статического метода вы вызываете имя класса как область видимости.

Так что на самом деле нет смысла переопределять, вы все равно это скрываете.

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...