具有多种类型支持的 Java 泛型

发布于 2024-11-05 17:27:10 字数 576 浏览 2 评论 0原文

假设我们有一个这样的接口...

接口 ICalculator{ 无效计算(T obj); }

其中我们的泛型类型是一个抽象类...

public abstract class CalculableObject{...}

具有多个具体类型...

public class TypeA extends CalculableObject{.. .}

public class TypeB extends CalculableObject{...}

如果需要为多个 CalculableObject 类型定义计算方法,您将如何定义 Calculator 对象的实现?

即 -

public CalculatorAB;实现 ICalculator{
void 计算(TypeA obj){...}
void 计算(TypeB obj){...}
}

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?

ie -

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

半岛未凉 2024-11-12 17:27:10

由于类型擦除,你不能。请参阅:通用接口出现错误:接口观察者不能使用不同的参数多次实现:

我会做的是使用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){...}
}

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:

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. 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){...}
}
娇柔作态 2024-11-12 17:27:10

我敢说,如果你想这样做,也许你的设计中的其他地方有问题。但除了已经提到的替代方案之外,您还可以仅使计算方法在接口中通用,而不是整个接口。那么子接口可以是通用的,也可以简单地定义您想要的新方法。

像这样:

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

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
错爱 2024-11-12 17:27:10

你不能。 (与流行的看法相反,它可以相对容易地在没有运行时具体化的情况下实现。但事实并非如此。)

通常,“主”类型的多个子类型化是一个坏主意。拥有一个对象,该对象具有返回适当的计算器的方法(请不要使用匈牙利语!)。

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 Calculators (no Hungarian please!).

皓月长歌 2024-11-12 17:27:10

使用 enum

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

然后可以保证 TypeAB 存在,并且它们都扩展CalculableObject

这还使您能够简单地将 Type.A 作为 Type传递给 calculate 方法CalculableObject,而不是将其与 A、B、C、D 等混杂在一起。

Use an 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.

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.

享受孤独 2024-11-12 17:27:10

您可以在 CalculableObject 类中定义“计算”所需的方法。然后,在 CalculatorAB 中,您只需调用给定对象上的这些方法。

You define the methods you need to "calculate" in the CalculableObject class. Then, in CalculatorAB you just call those methods on the given object.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文