【问题标题】:Return a nested class type in Java在 Java 中返回嵌套类类型
【发布时间】:2010-10-18 09:12:56
【问题描述】:

我有一个具有抽象 getType() 方法的基类。我希望子类能够实现此方法并提供要使用的实际类。

在代码中,类似于以下内容:

public abstract class A {
    public static interface Tile;

    protected abstract Class<Tile> getTileClass();
}

public class B extends A {
    public static class MyTile implements A.Tile { }

    @Override
    protected abstract Class<A.Tile> getTileClass() {
        MyTile t = new MyTile();  // WORKS 
        return MyTile;            // ERROR HERE
    }
}

这里的问题是我在标记的行中得到“MyTile 无法解决”。所以我试图返回这个:

return new MyTile().getClass()

但现在 Eclipse 告诉我:

类型不匹配:无法从 Class&lt;capture#1-of ?扩展 B.MyTile&gt; to Class&lt;A.Tile&gt;

我什至不确定 Eclipse 中是否存在错误(捕获#1?)。

接下来,我将放弃接口并尝试使用抽象基 Tile 类。在 Eclipse 的帮助下,我最终得到了以下似乎可以编译的代码:

public abstract class A {
    public static abstract class Tile;

    protected abstract Class<? extends Tile> getTileClass();
}

public class B extends A {
    public static class MyTile exends A.Tile { }

    @Override
    protected abstract Class<? extends A.Tile> getTileClass() {
        return new MyTile().getClass();  // WORKS
        return MyTile;                   // "Cannot be resolved"
    }
}

所以我基本上似乎有三个问题:

1) 是否有可能让它与 A.Tile 作为接口一起使用?

2) 使用基类时,Class&lt;? extends X&gt; 真的是正确的方法吗?

3) 如何从方法内部返回嵌套的 B.MyTile 类引用?不得不做new MyTile().getClass() 是不对的,不是吗?

【问题讨论】:

  • 可能返回 Class 而不是非反射对象是个坏主意。
  • @Tom 在检查类型的上下文中返回一个 Class 是一种非常常见的模式,它允许您检查例如集合的 checked 类型, 在运行时。我不知道其他方法,事实上......

标签: java class oop nested-class


【解决方案1】:

泛型和协变类型覆盖不能很好地协同工作。您必须明确声明 getTileClass() 返回一个可以是 A.Tile 的 子类 的类。

您还可以使用 MyTile.class 访问 MyTile 的类对象,而无需实例化它。

试试这个:

public abstract class A {
    public static interface Tile;

    protected abstract Class<? extends Tile> getTileClass();
}

public class B extends A {
    public static class MyTile implements A.Tile { }

    @Override
    protected Class<MyTile> getTileClass() {
        return MyTile.class;
    }
}

将 A 设为泛型会更好。您仍然必须在类类型定义中使用 extends,但可以更具体一点:

public abstract class A<T extends A.Tile> {
    public static interface Tile;

    protected abstract Class<? extends T> getTileClass();
}

public class B extends A {
    public static class MyTile implements A.Tile { }

    @Override
    protected Class<MyTile> getTileClass() {
        return MyTile.class;
    }
}

【讨论】:

  • 可能是复制粘贴错误,但是抽象方法可以有主体吗?正确的应该是“protected Class getTileClass { ...”
  • @Carlos 是的,那是一个过度渴望的 c/p
  • 好答案。这是仅仅因为协方差还是一般情况下的问题?
  • @Tom 不,我的意思是 。只要尝试让一个类 B 扩展 A,然后一个类 C 扩展 B,它定义了 getTileClass(),你就会明白为什么...
  • @Uri Covariance 应该适用于所有类型,甚至是泛型。然而,编译器只知道如何在擦除类型上应用协方差,而不是在 type arg 上。通常,添加 extends T> 是件好事……你永远不知道什么时候有人会尝试扩展你的类……
【解决方案2】:
public abstract class A {
    public static interface Tile {};

    // I return something that is-a Tile
    protected abstract Tile getTileClass();
}

public class B extends A {
    public static class MyTile implements A.Tile { }

    @Override
    protected abstract Tile getTileClass() {
        return new MyTile();
    }
}

不需要泛型,你只想说你返回一个 Tile 或 Tile 子类。

顺便说一句,类中的公共静态接口是“代码气味”;要么使其受到保护,因此只有 A 的子类才能实现 Tile,要么将其放在自己的顶级接口中。加入一个但允许任何人实施它会发出一个混合的信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多