繁体   English   中英

扩展不止一种类型的泛型

[英]Generics that extends more than one type

将扩展类并同时实现接口的对象分配给变量。 我有这样的方法

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

这意味着 instance() 返回的对象是一个组件并且实现了 MyInterface。 我可以做类似的事情

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

现在我想将返回的值分配给一个变量:如何声明变量以便为变量带来所有泛型信息?

我希望能够做这样的事情:

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

还有这个:

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

在我看来,这个问题与为什么我不能在具有多个边界的类型参数中使用类型参数中的问题不同 因为我没有在泛型类声明中使用类型参数。

根据 John Bollinger 的建议,我做了一些其他实验并找到了一个可能的“解决方案”(但不像我要求的那么简单)。 但我认为我的 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

我希望能够做这样的事情:

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

恐怕不是。 Java 不提供通用变量,而且在大多数情况下这样做是没有意义的。 您可以将实例变量的类型声明为其类的类型参数,但不能像方法一样为任何变量赋予其自己的、独立的类型参数。 无法声明具有两种类型的变量。

如果您希望能够使用myVar的两个方面,如示例中所示,则必须将其类型声明为扩展或实现两个超类型的特定类型。 有两种主要的替代方案:

  1. 使instance()方法返回这样的类型。 这可能是最自然的解决方案,因为该方法不依赖于T用于除挂起超类型之外的任何目的。

     public class MyInterfaceComponent extends Component implements MyInterface { // ... } MyInterfaceComponent myVar = instance();
  2. 动态生成这种类型的包装器对象,该对象将扩展类和实现接口的通用对象适应于这样做的特定类型。

     MyInterfaceComponent myVar = wrap(instance());

只有当您有可能需要处理扩展类并实现接口的外部提供的对象,但您无法控制其特定类时,后者才对我有意义。

暂无
暂无

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

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