Java Generics с поддержкой нескольких типов - PullRequest
0 голосов
/ 10 мая 2011

Скажем, у нас есть интерфейс как таковой ...

interface ICalculator<T extends CalculableObject>{ void calculate(T obj); }

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

public abstract class CalculableObject{...}

с несколькими конкретными типами ...

public class TypeA extends CalculableObject{...}

public class TypeB extends CalculableObject{...}

Как вы будете определять реализацию объекта Calculator, который требуетметод вычисления, который будет определен для нескольких типов CalculableObject?

т.е. -

public CalculatorAB<?> implements ICalculator{<br> void calculate(TypeA obj){...}<br> void calculate(TypeB obj){...}<br> }

Ответы [ 5 ]

2 голосов
/ 10 мая 2011

Из-за стирания типа вы не можете. См .: Получение ошибки для универсального интерфейса: интерфейс Observer не может быть реализован более одного раза с разными аргументами:

Что бы я сделал, это использовал бы delgate и ваш CalculatorAB, но он просто не реализует ICalculator, или еще лучше, если CalculatorAB реализует ICalcuator. Затем ваш метод может проверить экземпляр и перейти к соответствующему методу.

public CalculatorAB implements ICalculator<CalculableObject> {
  void calculate(CalculableObject obj){
    if(obj instanceof TypeA)
      calculate((TypeA)obj);
    else if(obj instanceof TypeB)
      calculate((TypeB)obj);
  }
  void calculate(TypeA obj){...}
  void calculate(TypeB obj){...}
}
1 голос
/ 10 мая 2011

Вы не можете. (Вопреки распространенному мнению, его можно относительно легко реализовать без ограничения времени выполнения. Но это не так.)

Как правило, множественные подтипы «основных» типов - плохая идея. Есть один объект, который имеет методы, которые возвращают соответствующие Calculator s (не венгерский, пожалуйста!).

0 голосов
/ 10 мая 2011

Я осмелюсь сказать, что если вы хотите сделать это, возможно, что-то не так, в другом месте вашего дизайна.Но помимо уже упомянутых альтернатив, вы можете сделать только метод вычисления универсальным в интерфейсе, а не весь интерфейс.Тогда подынтерфейсы могут быть универсальными или просто определять новые методы, которые вы хотите.

Например:

public static abstract class CalculableObject{}

public static class TypeA extends CalculableObject{}
public static class TypeB extends CalculableObject{}
public static class TypeC extends CalculableObject{}

public interface ICalculator{
    <T extends CalculableObject> void calculate(T obj);
}

public static class CalculatorAB implements ICalculator{

    void calculate(TypeA obj){
        System.out.println("TypeA");
    }
    void calculate(TypeB obj){
        System.out.println("TypeB");
    }

    @Override
    public <T extends CalculableObject> void calculate(T obj) {
        System.out.println("CalculableObject");
    }
} 

public static void main(String args[]){
    TypeA a = new TypeA();
    TypeB b = new TypeB();
    TypeC c = new TypeC();

    CalculatorAB ab = new CalculatorAB();

    ab.calculate(a);
    ab.calculate(b); 
    ab.calculate(c);
}

Это делает

TypeA
TypeB
CalculableObject
0 голосов
/ 10 мая 2011

Вы определяете методы, которые вам нужно «вычислить» в классе CalculableObject.Затем в CalculatorAB вы просто вызываете эти методы для данного объекта.

0 голосов
/ 10 мая 2011

Используйте enum:

public enum Type extends CalculableObject {
    A
    {
        @Override
        public void doSomething() { }
    },
    B;
}

Затем вы гарантируете, что Type 'A и B существуют, и что они оба расширяют CalculableObject.

Это также позволяет вам просто передать Type.A методу calculate как Type или CalculableObject, вместо того, чтобы загромождать его A, B, C, D и т. Д..

...