Java: проблема с определением типа Generics & Collection - PullRequest
0 голосов
/ 26 декабря 2008

У меня есть класс DataSet с различными конструкторами, каждый из которых определяет свой тип переменной. Это может выглядеть примерно так:

public class DataSet
{
    private HashSet Data;


    public DataSet( DataObject obj )
    {
        Data = new <DataObject>HashSet();
        Data.add( obj );
    }

    public DataSet( ObjectRelationship rel )
    {
        Data = new <ObjectRelationship>HashSet();
        Data.add( rel );
    }
    // etc.

Примечание: я еще не тестировал этот код из-за неполных частей (которые я сейчас создаю).

В функции, которую я сейчас создаю, getDataObjects(), мне нужно вернуть все объекты DataObject, которые представляет этот набор. В случае конструкторов, которые инициируют класс HashSet, Data с типами, отличными от DataObject (например, как указано выше ObjectRelationship), очевидно, что внутри них не будет храниться никаких объектов DataObject. В этом случае мне нужно иметь возможность определить тип, с которым был инициирован «Данные» HashSet (например, сказать, является ли он «ObjectRelationship» или нет). Как мне это сделать?



tl; dr : Как мне указать тип, с которым в моем коде был инициирован Collection (в данном случае HashSet) (например, с помощью оператора if или switch или чего-то еще)?

Ответы [ 8 ]

4 голосов
/ 26 декабря 2008

Звучит так, как будто вы хотите сделать весь класс общим: добавить параметр шаблона в объявление для класса и определить функции HashSet и поиска, используя этот параметр шаблона для типов.

Сейчас я парень .Net, поэтому я не могу дать вам синтаксис Java, но, используя синтаксис C # , это будет выглядеть примерно так:

public class DataSet<T>
{
    private Set<T> Data;

    public DataSet( T obj )
    {
        Data = new HashSet<T>();
        Data.add( obj );
    }

    public Iterator<T> getDataObjects()
    {
        return Data.iterator;
    }
}
1 голос
/ 26 декабря 2008

Похоже, ваш дизайн нуждается в переосмыслении.

Также, чтобы прояснить Generics; вы не можете получить доступ к типу во время выполнения. Параметр type предназначен только для проверки во время компиляции и полностью отсутствует (стирание типа) во время выполнения.

1 голос
/ 26 декабря 2008

Вы можете использовать карту для набора

HashMap <Class<?>, HashSet<Object>> data;
HashSet temp = data.get(DataObject.class);
if(temp == null)
{
   temp = new HashSet();
   data.put(DataObject.class, temp);
}
temp.add(obj);

Тогда вы получите лучшее из обоих миров.

1 голос
/ 26 декабря 2008

Вы можете получить объект из набора и проверить его тип.

Или вы можете иметь несколько наборов для разных типов.

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

Или вы можете создать прокси-объект для HashSet, используя последний метод.

0 голосов
/ 26 декабря 2008

Я не знаю, что DataObject дает вам сверх Объекта.

Я думаю, что объектно-ориентированный подход к вашей проблеме будет использовать классы, которые отражают вашу область интересов (например, Счет, Клиент и т. Д.). Слой персистентности скрывал бы детали персистентности.

Обычный способ сделать это - использовать объект доступа к данным, который в Java может выглядеть следующим образом:

public interface GenericDao<T>
{
    T find(Serializable id);
    List<T> find();
    void save(T obj);
    void update(T obj);
    void delete(T obj);
}

Теперь вы имеете дело с объектами, а не с вещами, которые пахнут реляционными базами данных. Все детали CRUD скрыты за интерфейсом DAO.

0 голосов
/ 26 декабря 2008

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

Это добавит незначительные издержки в процессе создания каждого объекта DataSet правильного типа, но я полагаю, что так оно и есть.

0 голосов
/ 26 декабря 2008

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

Установите свойство в соответствующем конструкторе. Это позволяет обойти извлечение элемента из коллекции, чтобы проверить его тип.

псевдо-код:

public class DataSet
{
private HashSet Data;
private Type _iw = null;
public Type InitializedWith { return _iw; }

public DataSet(DataObject)
{
...
_iw = typeof(DataObject);
}

public DataSet(ObjectRelationship)
{
...
_iw = typeof(ObjectRelationship)
}
0 голосов
/ 26 декабря 2008

Что предлагает этот класс, чего нет у CachedRowSet?

Извините, я не считаю это очень хорошей абстракцией. Если бы я был членом вашей команды, я бы не использовал его.

Ваш синтаксис мне тоже не выглядит правильным. IntelliJ согласен со мной: он не скомпилируется.

Это делает:

import java.util.HashSet;
import java.util.Set;
import java.util.Arrays;

public class DataSet
{
    private Set<DataObject> data;


    public DataSet(DataObject obj)
    {
        this.data = new HashSet<DataObject>();
        data.add(obj);
    }

    public DataSet(DataObject[] objs)
    {
        data = new HashSet<DataObject>();
        data.addAll(Arrays.asList(objs));
    }
    // etc.
}

Все еще плохая абстракция. Переосмыслить.

...