Чтение поля содержащего реализации интерфейса
У меня есть объект с полем:
public List<Mod> mods;
Mod это интерфейс. Есть несколько классов, реализующих его.
Мой yaml выглядит так:
mods:
mod1: # Идентификатор мода
id: "Yaml test" # Данные мода
mod2:
type: SEMI
Идентификатор не совпадает с названием класса
Как я могу эффективно прочитать этот объект?
Ответы (1 шт):
Автор решения: Nowhere Man
→ Ссылка
Фактически содержимое yaml-файла соответствует не списку, а словарю (мапе) Map<String, Mod> mods, поэтому для решения данной проблемы есть два способа:
- Изменить Java-код, чтобы он соответствовал формату
yaml-файла.
Тогда можно будет извлечь коллекцию значений из словаря/мапы при помощи стандартного методаMap::values:
public Map<String, Mod> mods; // List<Mod> -> Map<String, Mod>
public List<Mod> modsAsList() {
return mods == null ? null : new ArrayList<>(mods.values());
}
- Изменить структуру
yaml-файла, чтобы она соответствовала спискуList<Mod>(например, ключиmod1,mod2станут комментариями):
mods:
-
#mod1
id: Yaml test
-
#mod2
type: SEMI
Обновление
Если требуется получить словарь классов экземпляров Mod на основании данных из yaml-файла, то следует создать новый экземпляр словаря с соответствующей типизацией и сгенерировать его на основании словаря Map<String, Mod>, используя к примеру "ленивую" загрузку:
public Map<String, Mod> mods; // первый вариант решения
private Map<String, Class<? extends Mod>> modClasses;
public Map<String, Class<? extends Mod>> getModClasses() {
if (modClasses == null && mods != null) {
modClasses = mods.entrySet()
.stream() // Stream<Map.Entry<String, Mod>>
.collect(Collectors.toMap(
Map.Entry::getKey, e -> e.getValue().getClass()
));
}
return modClasses;
}