简体   繁体   English

具有多种类型支持的Java Generics

[英]Java Generics with multiple type support

Say we have an interface as such... 假设我们有这样的界面......

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

where our generic type is an abstract class... 我们的泛型类型是一个抽象类...

public abstract class CalculableObject{...}

with multiple concrete types... 有多种具体类型......

public class TypeA extends CalculableObject{...}

public class TypeB extends CalculableObject{...}

How would you go about defining an implementation of the Calculator object that requires a calculate method to be defined for multiple CalculableObject types? 您将如何定义Calculator对象的实现,该实现需要为多个CalculableObject类型定义计算方法?

ie - 即 -

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

Because of type erasure, you can't. 因为类型擦除,你不能。 See: Getting error for generic interface: The interface Observer cannot be implemented more than once with different arguments: 请参阅: 获取通用接口的错误:接口Observer不能使用不同的参数多次实现:

What I would do is use a delgate and have your CalculatorAB but it simply doesn't implement ICalculator, or better yet, have CalculatorAB implements ICalcuator. 我要做的是使用delgate并使用您的CalculatorAB,但它只是没有实现ICalculator,或者更好的是,CalculatorAB实现了ICalcuator。 Your method can then check instance of and forward to the appropriate method. 然后,您的方法可以检查实例并转发到适当的方法。

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){...}
}

You can't. 你不能。 (Contrary to popular belief, it could relatively easily be implemented without runtime reification. But it isn't.) (与普遍看法相反,它可以相对容易地在没有运行时具体化的情况下实现。但事实并非如此。)

Generally multiple subtyping of "main" types is a bad idea. 通常,“主要”类型的多个子类型是一个坏主意。 Have one object that has methods that returns appropriate Calculator s (no Hungarian please!). 有一个对象有返回适当的Calculator的方法(请不要匈牙利!)。

Use an enum : 使用enum

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

You are then guaranteed that Type 's A and B exist, and that they both extend the CalculableObject . 然后保证TypeAB存在,并且它们都扩展了CalculableObject

This also enables you to simply pass in Type.A to the calculate method as a Type or CalculableObject , rather than cluttering it with A, B, C, D, etc. 这也使您能够简单地在传递Type.Acalculate方法作为Type CalculableObject ,而不是与A,B,C,d,等等弄乱它

I daresay that if you want to do this, perhaps there is something wrong, elsewhere in your design. 我敢说,如果你想这样做,也许在你的设计的其他地方有一些错误。 But besides the already mentioned alternatives, you could make just the calculate method generic in the interface, and not the whole interface. 但除了已经提到的替代方案之外,您可以在接口中仅使计算方法通用,而不是整个接口。 Then the subinterfaces can be generic or simply define the new methods you want. 然后子接口可以是通用的,或者只是定义所需的新方法。

Like this: 像这样:

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);
}

This renders 这呈现

TypeA
TypeB
CalculableObject

You define the methods you need to "calculate" in the CalculableObject class. 您可以在CalculableObject类中定义“计算”所需的方法。 Then, in CalculatorAB you just call those methods on the given object. 然后,在CalculatorAB中,您只需在给定对象上调用这些方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM