Вообщем по просьбе Viktor Davion объясняю (в 140 твиттеровских символов не уложился), отчасти, что побудило к посту ненависти. Под катом, т.к. содержит плоды работы воспалённого мозга.
Вот набросок того кода, который побудил этот пост (упрощённый, по памяти):
- package me.drobushevich.blog.generics;
- public abstract class AbstractWorker {
- public abstract void execute();
- }
- package me.drobushevich.blog.generics;
- public class Config {
- public final String name;
- public Config(final String name) {
- this.name = name;
- }
- }
- package me.drobushevich.blog.generics;
- public abstract class AbstractWorkerFactory<C extends Config> {
- public abstract AbstractWorker createWorker(final C configuration);
- }
- package me.drobushevich.blog.generics;
- import java.util.ArrayList;
- import java.util.List;
- public class Service {
- private final List<AbstractWorker> workers;
- public Service(final AbstractWorkerFactory<? extends Config> factory, List<Config> configurations) {
- workers = new ArrayList<AbstractWorker>();
- for (Config configuration : configurations) {
- // не компилится The method createWorker(capture#1-of ? extends Config) in the type AbstractWorkerFactory<capture#1-of ? extends Config> is not applicable for the arguments (Config)
- workers.add(factory.createWorker(configuration));
- }
- }
- }
Всё очень просто, фабрика, которая по Generic конфигурации строит объекты. Сервису должно быть пофигу безразлично, что за конфигурация и т.п. Сервис выглядит странно, т.к. можно было просто передать набор работников, но так надо, тащить все зависимости в блог лениво.
Вроде ж выглядит логично, create метод принимает потомка конфигурации, мы потомка конфигурации и даём...
Маленькие пометки.
Зачем вообще дженерики О.о Просто для маленьких вкусностей, вот таких:
- package me.drobushevich.blog.generics;
- public class ReadConfig extends Config {
- public final boolean option;
- public ReadConfig(final String name, final boolean option) {
- super(name);
- this.option = option;
- }
- }
- package me.drobushevich.blog.generics;
- public class ReadWorker extends AbstractWorker {
- public ReadWorker(final boolean option) {
- }
- @Override
- public void execute() {
- }
- }
- package me.drobushevich.blog.generics;
- public class ReadWorkerFactory extends AbstractWorkerFactory<ReadConfig> {
- @Override
- public AbstractWorker createWorker(final ReadConfig configuration) {
- // Обратим внимание на эту строчку (:
- return new ReadWorker(configuration.option);
- }
- }
Проблему можно в принципе решить например вот так:
- public Service(final AbstractWorkerFactory<Config> factory, final List<Config> configurations) {
- // но не работает
- new Service(new ReadWorkerFactory(), configurations);
Вообщем жду предложений (; Не исключается возможность ошибки в ДНК. В последнее время за мной было замечено предложение не самых здравых идей ):
Главная проблема, что Generics это уровень компиляции, jvm о них ничего не знает. Кстати, можно посмотреть не очень давнее выступление Джеймса Гослинга, в частности он там говорит, что Generics были реализованы как компромисс между усложнением и полезностью. Трудно спорить (: особенно с ним (:
Кстати, там же он хвалит Scala, вот где, мне нравятся generics, так это в там (к самому языку отношусь не так, хотя тот факт, что на нём можно писать так как на java, но с доп. плюшками, это не плохо).
Если будет настроение, на выходных напишу пост о Generics в Scala. Всё таки generics высших порядков это звучит интересно (:
UPDATE (после обсуждения на stackoverflow):
- public AbstractWorker caramba(final AbstractWorkerFactory<? super ReadConfig> factory, ReadConfig configuration) {
- return factory.createWorker(configuration);
- }
- new Service().caramba(new WorkerFactory(), new ReadConfig("1", false));
- new Service().caramba(new ReadWorkerFactory(), new ReadConfig("2", true));
Лол. Джава не нужна.
ОтветитьУдалитьА ты на стековерфлове вопрос задавал? Там гуры быстро ответят.
Вопрос, задал просто на всякий случай. Это больше возмущение, так как это не возможно.
ОтветитьУдалитьНу дабы, ещё немного посмеяться, вот ещё один пёрл, того как в самом сане используют дженерики:
Map<Integer, Double> map = new HashMap<Integer, Double>();
map.put(1, 2.1);
//map.put(2.1, 1); - ok, it is not working
map.get("caramba"); // Is it funny? But it is work: get(Object key)
Нифигово они быстро там в коменты на спамили О.о
ОтветитьУдалитьВообщем по результатам обсуждения на stackoverflow обновил пост солюшеном, который относительно не плохо подошел.
ОтветитьУдалитьВообщем по результатам обсуждения на stackoverflow обновил пост солюшеном, который относительно не плохо подошел.
ОтветитьУдалитьХотя в последнее время много тупил, так что на всякий случай спросил
ОтветитьУдалить