【问题标题】:Java - Defining a member that extends class A and implements interface BJava - 定义扩展类 A 并实现接口 B 的成员
【发布时间】:2015-09-18 17:10:35
【问题描述】:

我有一个变量必须满足两个条件,我想在定义中设置它们

我知道我可以使用单个变量来定义任一条件,就像在这些示例中的任何一个中一样

private Class<? extends A> variable; //or
private A variable; //or
private Class<? extends B> variable; //or
private B variable;

但是有没有办法让变量同时满足这两个条件?

我希望有这样的东西

private Class<? extends A implements B> variable;

但是当我需要调用它或存储它的多个副本时,如果不进行类型转换,我找不到任何方法来做到这一点

【问题讨论】:

  • 如果你有一个抽象类 C 扩展 A 并实现 B 怎么办?私人课 变量;
  • 使你的类成为泛型,声明一个类型变量T,边界为AB,为T extends A &amp; B,然后声明一个类型为T的字段。

标签: java object generics interface anonymous-types


【解决方案1】:

您可以声明具有多个边界的类型参数,例如:

public static <T extends A & B> void test(Class<T> clazz)

但是你不能声明一个有多个边界的变量:

private Class<? extends A & B> variable;  // doesn't work

您可以创建一个扩展A 并实现BabstractC,因此只需要一个绑定。

abstract class C extends A implements B {}

然后:

private Class<? extends C> variable;

【讨论】:

  • 问题来了:A类是Android框架的一部分;接口 B 是我定义的接口; C 类是我自己的,它扩展了 A; E类是我自己的,需要扩展D(也是Android的一部分),扩展A;所以我实际可以使用的可能变量将是 C 或 E 的实例,但它们唯一的共同父级是 A,这不是我可以控制的。
【解决方案2】:

虽然 Java 不直接支持像 A&amp;B 这样的交集类型,但此类类型确实出现在类型参数边界和捕获转换中。我们可以用抽象层来表达A&amp;B

public class ValueAB<T extends A&B>
{
    public final T v;

    // constructor ...
}

public class ClassAB<T extends A&B>
{
    public final Class<T> clazz;

    // constructor ...
}

我们使用包装器ValueAB, ClassAB而不是A&amp;B, Class&lt;? extends A&amp;B&gt;

    ClassAB<?> clazz = new ClassAB<>(Foo.class);   

    ValueAB<?> value = new ValueAB<>(clazz.c.newInstance());

    value.v.methodOfA();
    value.v.methodOfB();

此解决方案需要为 As 和 Bs 的每个组合使用一个包装器。


另一种解决方案是只使用A作为类型参数绑定; B 将由通配符绑定提供。如果您需要在使用站点表达多个A&amp;B1, A&amp;B2, ... 类型,这可能会更好。

public class ValueA<T extends A>
{
    public final T v;
    ...
}


public class ClassA<T extends A>
{
    public final Class<T> c;
    ...
}

---

    ClassA<? extends B> clazz = new ClassA<>(Foo.class);

    ValueA<? extends B> value = new ValueA<>(clazz.c.newInstance());

如果在这些情况下通配符的工作方式令人困惑,请参阅我的article on wildcard


第三种解决方案在包装器声明处不含 A 或 B;使用网站提供A和B。

public class Value<T extends S, S>
{
    public final T v;
    ...
}


public class Clazz<T extends S, S>
{
    public final Class<T> c;
    ...
}

---

    Clazz<? extends A, B> clazz = new Clazz<>(Foo.class);

    Value<? extends A, B> value = new Value<>(clazz.c.newInstance());

然而这可能太令人困惑了。

【讨论】:

    猜你喜欢
    • 2014-01-02
    • 1970-01-01
    • 2016-10-24
    • 2014-11-02
    • 2012-12-10
    • 2013-09-25
    • 2019-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多