简体   繁体   English

扩展不止一种类型的泛型

[英]Generics that extends more than one type

Assign to a variable an object that extends a class and implements an Interface at the same time.将扩展类并同时实现接口的对象分配给变量。 I have a method like this我有这样的方法

public static <T extends Component & MyInterface> T instance() {
  if (test1) return new MyLabel();
  if (test2) return new MyCombo();
  if (test3) return new MyText();
}

class MyLabel extends JLabel implements MyInterface {
  ...
}

class MyCombo extends JComboBox implements MyInterface {
  ...
}

class MyText extends JTextField implements MyInterface {
  ...
}

this means the instance() returned object is a Component AND implements MyInterface.这意味着 instance() 返回的对象是一个组件并且实现了 MyInterface。 and I can do something like我可以做类似的事情

instance.setEnable(true); // calling a Component method
instance.foo();           // calling a MyInterface method

Now I want to assign the returned value to a variable: how to declare the variable in order to bring with the variable all the Generics info?现在我想将返回的值分配给一个变量:如何声明变量以便为变量带来所有泛型信息?

I expect to be able to do something like this:我希望能够做这样的事情:

static <T extends Component & MyInterface> T myVar = instance();
myVar.setEnable(true); // calling a Component method
myVar.foo();           // calling a MyInterface method

and also this:还有这个:

static void f1(Component c) {}
static void f2(MyInterface c) {}
f1(myVar);
f2(myVar);

In my opinion the question is different from the one in Why can't I use a type argument in a type parameter with multiple bounds?在我看来,这个问题与为什么我不能在具有多个边界的类型参数中使用类型参数中的问题不同 because I'm not using a type parameter inside a generic class declaration.因为我没有在泛型类声明中使用类型参数。

Based on John Bollinger suggestion I do some other experiments and found a possible "solution" (however not as simple as I required).根据 John Bollinger 的建议,我做了一些其他实验并找到了一个可能的“解决方案”(但不像我要求的那么简单)。 But I think my wrap() method is different from what John meant.但我认为我的 wrap() 方法与 John 的意思不同。

public final class Wrap<X extends Component & MyInterface> {
    public final X x;
    public Wrap(X x) {
        this.x = x;
    }
}
public static <X extends Component & MyInterface> Wrap<X> wrap(X x) {
    return new Wrap<X>(x);
}

static Wrap<?> myVar = wrap(instance());
myVar.x.setEnabled(true);    // Component method
f1(myVar.x);                 // Component parameter
myVar.x.foo();               // MyInterface method
f2(myVar.x);                 // MyInterface parameter

I expect to be able to do something like this:我希望能够做这样的事情:

 static <T extends Component & MyInterface> T myVar = instance(); myVar.setEnable(true); // calling a Component method myVar.foo(); // calling a MyInterface method

I'm afraid not.恐怕不是。 Java does not offer generic variables, and for the most part it wouldn't make sense to do so. Java 不提供通用变量,而且在大多数情况下这样做是没有意义的。 You may declare the type of an instance variable as a type parameter of its class, but you cannot give any variable its own, independent type parameter like you can a method.您可以将实例变量的类型声明为其类的类型参数,但不能像方法一样为任何变量赋予其自己的、独立的类型参数。 There is no way to declare a variable that has two types.无法声明具有两种类型的变量。

If you want to be able to make use of both facets of myVar , as shown in the example, then its type must be declared as a specific type that extends or implements both supertypes.如果您希望能够使用myVar的两个方面,如示例中所示,则必须将其类型声明为扩展或实现两个超类型的特定类型。 There are two main alternatives for that:有两种主要的替代方案:

  1. Make the instance() method return such a type.使instance()方法返回这样的类型。 This is probably the most natural solution, since that method doesn't depend on T for any purpose other than to hang supertypes upon.这可能是最自然的解决方案,因为该方法不依赖于T用于除挂起超类型之外的任何目的。

     public class MyInterfaceComponent extends Component implements MyInterface { // ... } MyInterfaceComponent myVar = instance();
  2. Dynamically generate a wrapper object of such a type that adapts general objects that extend the class and implement the interface to a particular type that does so.动态生成这种类型的包装器对象,该对象将扩展类和实现接口的通用对象适应于这样做的特定类型。

     MyInterfaceComponent myVar = wrap(instance());

The latter makes sense to me only if there's a possibility that you need to handle externally-provided objects that extend the class and implement the interface, but whose specific class you cannot control.只有当您有可能需要处理扩展类并实现接口的外部提供的对象,但您无法控制其特定类时,后者才对我有意义。

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

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