2013-09-22 3 views
1

Я пытаюсь использовать generics для получения возвращаемого значения на основе аргумента enum.Использование перечисления в общем выражении для определения типов возвращаемых значений

public enum DataTypes { 
    MEAL, EXAM_RESULT, SPORTS,ECA, HEATLH; 
} 


public class GeneralData{ 
    String getDataFile(); 
} 

public class SportsData extends GeneralData{ 
    getDailyCalroiesBurnt(); 
    getSwimmingStyle(); 
} 

public class HealthData extends GeneralData{ 
    getBloodGroup(); 
} 

Теперь я хочу, чтобы написать функцию "GetData (Datatypes тип данных)", который

  • при вызове с DataTypes.SPORTS возвращает объект Sportsdata
  • при вызове с DataTypes.HEATLH возвращает объект HealthData
  • для всех остальных объектов GeneralData.

Что-то вроде:

<T> T getData(DataTypes datatype){ 
    ... 
    ... 
} 

HealthData healthData = getData(DataTypes.HEATLH); 
SportsData sportsData = getData(DataTypes.SPORTS); 
GeneralData examData = getData(DataTypes.EXAM_RESULT); 
GeneralData mealData = getData(DataTypes.MEAL); 
GeneralData ecaData = getData(DataTypes.ECA); 

Как я могу сделать это с помощью дженериков, так что я не должен делать любой кастинг? Возможно ли это?

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

+2

Не возможно в таком виде - какой тип должен 'GetData (randomBool() DataTypes.SPORTS? : DataTypes.HEALTH) 'return? – Eric

+0

Я второй вариант «невозможно»/«не имеет смысла, учитывая систему типов Java». Также этот вопрос задают миллион раз. – millimoose

ответ

0

Это невозможно.

Кроме того, это, вероятно, не правильный способ делать то, что вы хотите (ИМО).

Что бы вы ожидали, что метод вернется, если он принимает переменную в качестве перечисления?

void MyMethod(DataTypes x) 
    { 
     /*?*/ result = getData(x); 


     // print result or whatever.. 
    } 

Тип возвращаемого метода - это информация времени компиляции. А именно, это должно быть известно при компиляции.

Значение параметра, с другой стороны, известно только во время выполнения.

Я не exacly знакомы с кодом, но я думаю, что это не плохое решение:

HealthData healthData = getHeatlhData(); 
    SportsData sportsData = getSportsData(); 
    GeneralData examData = getData(DataTypes.EXAM_RESULT); 
    GeneralData mealData = getData(DataTypes.MEAL); 
    GeneralData ecaData = getData(DataTypes.ECA); 
    GeneralData ecaData = getData(x); 

Я думаю, что это разумно.

Вместо того, чтобы иметь много значений if-else-if для значения перечисления, просто используйте еще несколько методов. Это на самом деле аккуратно.

Если ваш программист знает значение DataType, которое он хочет, он будет использовать соответствующий метод.

Если это переменная, используйте общий метод.

1

Типы вариантов в Java и большинство других широко используемых языков программирования - это боль в заднице. См. Мой blog post, который демонстрирует около 8 способов сделать варианты.

В вашем конкретном случае вы никогда не достигнете последних пяти строк кода, которые вы демонстрируете. Лучшее, на что вы можете надеяться, - всегда получать GeneralData и «опросить» его безопасным способом (например, с помощью шаблона посетителя).

1

Я бы передать объекты класса вместо:

<T extends GeneralData> T getData(Class<T> clazz); 

Тогда вы можете сделать:

SportsData sportsData = readData(SportsData.class); 
HealthData healthData = readData(HealthData.class); 
+0

Как вы реализуете getData()? Легко написать заглушку, которая будет компилироваться, но не фактический код. –

+0

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

+0

@JudgeMental: реализация может использовать, например, «Map , GeneralData> 'и использовать' clazz.cast() 'в некоторой степени. Система типов не гарантирует правильность поведения «полностью вниз», но если возникнет ошибка типа, это будет неудачный листинг в месте, где фактически происходит актерский состав. (Предупреждения «unchecked cast» предупреждают, что это не так много кода, который не доказуемо корректен компилятором, но «ClassCastException», где нет смысла.) – millimoose

Смежные вопросы