Проблемы с дженериками / системной архитектурой с использованием дженериков - PullRequest
1 голос
/ 04 июня 2011

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

Я занимаюсь разработкой библиотеки Java, и есть функция, которая будет вызывать платформу, которая будет возвращать информацию в формате JSON.Я хотел создать пространство имен, отвечающее за извлечение и анализ информации JSON в бизнес-объектах.Для этого я создал:

класс JSON - Имеет 2 метода:

protected JSONObject readJsonFromUrl(String url)

, откройте поток и загрузите файл JSON

public <T, U extends Parser> T readObjectFromUrl(String url, U parser) 

is "точка входа".Вызовет readJsonFromUrl и вызовет возвращенное значение для анализатора.

Класс Parser является абстрактным классом и имеет этот интерфейс

public abstract class Parser {

public abstract <T> T parse(JSONObject jsonObject);
}

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

public <T> T parse(JSONObject jsonObject) {
ContactList contactList = new ContactList();

    //Simplified for clearness
    contactList = parse(jsonObject);

return contactList;
}

Проблема заключается в следующем: я получаю ошибку компилятора, потому что он ожидает T, а не contactList.Если я изменяю на, подпись нового метода не совпадает с подписью родительского класса.Если я изменю объявление contactList на T contactList;, я не смогу вызвать некоторые методы, которые мне нужны (например, addContact).

Я получаю непатентованные дженерики неправильно?Подходят ли они для того, что я хочу в этом случае?Если это не так, как бы вы реализовали подобную функциональность?

Спасибо, Оскар

Редактировать: лучшее решение использовать объект вместо универсальных?Это не выглядит так красиво: (

Ответы [ 2 ]

3 голосов
/ 04 июня 2011

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

public abstract class Parser<T> {
    public abstract T parse(JSONObject jsonObject);
}

И ваша реализация будет выглядеть так:

public class Impl extends Parser<ContactList>{
    public abstract ContactList parse(JSONObject jsonObject){
        ContactList contactList = new ContactList();
        //Simplified for clearness
        contactList = parse(jsonObject);
        return contactList;
    }
}
2 голосов
/ 04 июня 2011

Возможно, вы захотите посмотреть, как Google Guice реализует метод Injector .getInstance:

<T> T getInstance(Class<T> type);

Это позволяет пользователю написать:

ContactList contactList = injector.getInstance(ContactList.class);

Применив этот шаблон к вашему анализатору, я думаю, вы могли бы избежать необходимости создавать разные классы анализатора для каждого типа, который вы хотите анализировать.Вместо этого вы можете просто иметь один класс Parser и вызывать такой метод:

ContactList contactList = parser.parse(jsonObject, ContactList.class);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...