2015-09-16 2 views
1

У меня есть метод, имеющий общий тип T в качестве аргументаКак я могу вызвать соответствующий метод с аргументом generic type?

private static <T> void doValidation(T[] pArray, int size, String firstName, String secondName) { 

    ... 

    for (int i = 0; i < size; i++) { 

     ... 

     validate(pArray[i]); 
    } 
} 

И тогда я другой метод дал конкретный тип, например, A, B и т.д ..

private static void validate(A a) { 

} 

private static void validate(B b) { 

} 

Я хотел бы он разрешает тип во время выполнения и вызывает соответствующий метод, основанный на типе, возможно ли это?

На данный момент я получаю

no suitable method found for validate(T) 
    method ValidateDataStructure.validate(A) is not applicable 
     (argument mismatch; T cannot be converted to A) 
    method ValidateDataStructure.validate(B) is not applicable 
     (argument mismatch; T cannot be converted to B) 
    where T is a type-variable: 
    T extends Object declared in method <T>doValidation(T[],int,String,String) 
---- 
(Alt-Enter shows hints) 

Он хочет меня бросить, конечно, аргумент ..

Я пытаюсь сделать порт Assimp, мое намерение состоит в том, чтобы быть как можно больше близко к структуре C. This - это функция, которую я пытаюсь установить прямо сейчас.

+2

Его невозможно. Generics - это время компиляции. –

+0

Вау, это было быстро :), так какой вариант вы бы предложили? – elect

+0

Вы не можете использовать полиморфизм для статических методов в Java. Вы можете использовать методы экземпляра и передавать экземпляры, которые предоставляют метод 'validate'. – khelwood

ответ

0

В зависимости от ваших конкретных потребностей, которые не совсем ясны из вашего вопроса, у вас есть несколько вариантов.

Похоже, вы, вероятно, на самом деле не нужен ваш метод doValidation вести себя по-разному в зависимости от T, а ваш метод validate вести себя по-разному в зависимости от типа времени выполнения своего аргумента. Это несколько другая проблема, но она легко разрешима: лучший вариант, вероятно, чтобы он делегирует на переопределение метода, что-то вроде:

private static <T extends Validatable> void validate(T arg) 
{ 
    arg.validate(); 
} 

(Вы должны определить соответствующий Validatable интерфейс, конечно, и параметр типа T в методе doValidation также должен быть объявлен как T extends Validatable).

Однако вышеуказанный вариант требует, чтобы вы могли модифицировать классы A и B (их реализовать Validatable). Другой вариант, не так чисто от точки зрения конструкции, но без этого ограничения, чтобы определить тип и отправку к другому способу, соответственно, путем введения метода validate с Object аргументом следующим образом:

private static void validate(Object arg) 
{ 
    if (arg instanceof A) { 
     validate((A) arg); 
    } 
    else if (arg instanceof B) { 
     validate((B) arg); 
    } 
    else { 
     throw new RuntimeException("Don't know how to validate object of class " + arg.getClass.getName()); 
    } 
} 
+0

Привет, я изменил свой вопрос, чтобы указать свое намерение – elect

+0

Хорошо, у меня есть (и вы имели в виду, что я, хотя вы, вероятно, сделали). «Общий аргумент типа» в значительной степени является красной селедкой. Если аргумент имел тип 'Object', вам все равно нужно отправить в соответствующую версию' validate'. – davmac

+0

Итак, что бы вы предложили мне пойти? – elect

1

Если вы хотите проверить типы, которые вы не можете продлить (например, Integer, String), , вы можете реализовать свою собственную динамическую диспетчеризацию. Например, вы можете создать карту валидаторов, как это (Java-8):

private static final Map<Class<?>, Consumer<?>> validators = new HashMap<>(); 

static { 
    validators.put(A.class, (A a) -> validate(a)); 
    validators.put(B.class, (B b) -> validate(b)); 
    ... 
} 

И написать метод выбора:

static <A> Consumer<A> getValidator(Class<A> clazz) { 
    // do nothing for unknown type 
    return (Consumer<A>)validators.getOrDefault(clazz,() -> {}); 
} 

Наконец, вы можете использовать его как это:

getValidator(value.getClass()).validate(value); 
+0

Хотя идея иметь карту для определения валидатора кажется хорошей идеей, у него есть один недостаток: он не обрабатывает наследование. У меня может быть отличный хороший валидатор для класса 'B' и всех его подклассов, но, используя этот подход, я должен создать запись карты для каждого подкласса. Конечно, это не может быть проблемой на практике. – davmac

+0

Я бы выбрал ответ Давмака, но в любом случае спасибо за написание вашего ответа, это очень интересно, +1 – elect

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