Возможно не данный вопрос будет не совсем правильным, но задача обстоит следующего характера:
Есть приложение, в котором много перечисляемых значений, по типу:
Gender:
MALE(R.string.female),
FAMALE(R.string.male)
HowMany:
EVERY_DAY(R.string.every_day),
ONCE_WEEK(R.string.once_week),
THREE_A_WEEK(R.string.three_a_week),
ONCE_MONTH(R.string.once_month),
ONCE_YEAR(R.string.once_year),
ETC(R.string.etc)
И так далее, они разных типов, некоторые возможно в будущем будут содержать не только строки. Они будут приходить из сервака, и храниться в БД.
По дизайну есть достаточно специфичная вьюшка, на подобие spinner
, который пришлось кастомизировать из нескольких инных вьюх. Так же использую DataBinding
и при помощи биндинга передаю enum во вьюшку, но хотелось бы как-то унифицировать вьюшку, так как таких вьюшек будет также много как и перечисляемых значений.
Вопрос: Как использовать в этой вьюшке унификацию принимаемых значений?
Сейчас список наполняю так:
for (item in Gender.values()) {
popupMenu.menu.add(item.resId!!)
}
Вместо Gender
нужна переменная, которая принимала бы любые Enum.
(Ответ дан с использованием java)
нужна переменная, которая принимала бы любые Enum
Ответ:
Для того, чтобы передать параметром метода любой Enum
следует использовать обобщение. Припустим, у нас есть метод, принимающий любой подтип Enum
и перебирает его константные значения:
public <E extends Enum<E>> void foo(E e){
for(Enum<E> item : e.getClass().getEnumConstants()){
// do something
}
}
Заметьте, что в этом примере не используется метод values()
. Все потому, что он не есть методом Enum
. Компилятор автоматически добавляет этот метод для всех подкласов enum
. Следовательно, если мы используем как параметр дженерик, то этого не будет достаточно для того, чтобы вызвать values()
.
Но
Конкретно в вашем примере это не получится. В цикле вы вызываете специфичное для Gender
поле resId
. Любой Enum
не подойдет.
Решение:
Для начала нужно создать интерфейс, который будут реализовывать все Enum
, что содержат ID ресурса. Пример:
public interface ResourceContainer {
int getResourceId();
}
Теперь, нужно имплементировать наш интерфейс во всех enum-классах, содержащих ресурс:
public enum Gender implements ResourceContainer {
MALE(R.string.male){
@Override
public int getResourceId() {
return this.idResource;
}
},
FEMALE(R.string.female){
@Override
public int getResourceId() {
return this.idResource;
}
};
protected int idResource;
Gender(int idResource) {
this.idResource = idResource;
}
}
Теперь модифицируем метод описаный выше под нашы нужды. Доставать Id ресурса будем через наш новый метод getResourceID()
:
public static <E extends Enum<E> & ResourceContainer> void updatePopupMenu(Class<E> resourceContainer,
PopupMenu popupMenu){
for (ResourceContainer enumValue : resourceContainer.getEnumConstants()) {
popup.getMenu().add(enumValue.getResourceId());
}
}
Так, как мы не можем инициализировать enum
, параметром метода следует передать класс. Вызов метода будет выглядеть так:
updatePopupMenu(Gender.class, popupMenu);
Как-то так.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Ребята перегрузка методов выполняетсь во время компиляции(Compile-Time) или во время выполнения (Run-Time) ?
Код ниже рисует линию, каждую секунду новуюКак можно сделать, чтобы новая линия добавлялась к старой? То есть хочу видеть через условно двадцать...
Нужно удалить повторяющиеся элементы связного списка спискаВывести сначала исходный связный список, затем уже с удалением