泛型名称冲突

6

请考虑以下内容:

public interface Foo<T> {
    public static class X{}
    public void foobar(T t); 
}

public class Bar<X> {
    Foo<X> foo = new Foo<X>() {
        public void foobar(X t) {}
    };
}

我发现没有办法表达我在Bar<X>中指的是X,而不是Foo.Xfoobar(X t)实现中。除了重命名Bar或静态内部类中的泛型参数X之外,还有其他方法吗?


2
这看起来不太对劲...你能在接口中嵌套一个公共类(即使是静态的)吗? - Daniel Pryden
是的,如果你重命名Bar的静态内部类或泛型参数,它就可以编译。 - Landei
2
@Daniel... 是的,你可以这样做。看起来有点滑稽,但它是完全有效的。 - Reverend Gonzo
2个回答

9

我认为没有办法消除类型参数的歧义,而且我认为这是一个合理的设计决策。

  1. 约定清楚表明类型参数应该尽可能只有一个字符长度,另一方面,其他类不应该有一个字符长度的名称。
  2. 如果您有消除歧义的能力,那么您将能够重新命名Bar <X>中的类型参数X。换句话说,如果您有能力说foobar(TypeParameter.X t),您将能够仅使用X以外的内容来作为Bar上的类型参数,重新命名X是避免名称冲突的方法。

不要忘记,类型参数名称在更多情况下不会泄露到其他类中。您永远不必强制使用某个特定的类型参数名称。因此,语言设计者并不认为这值得为语言增加复杂性。


我倾向于同意你的第二点,但不同意第一点:Java缺乏像闭包或元组这样基本的语法,这迫使你使用包装器。如果你在依赖这些包装器的代码上工作,你很快就会开始使用像FP这样的名称,而不是FunctionProduct(例如参见http://www.functionaljava.org)。 - Landei

0

编译器甚至不会去确定你是否指的是Foo.X,而是会考虑到类型参数X,除非你输入了类似于下面这样的内容:

public class Bar<X> {
    Foo<X> foo = new Foo<X>() {
        public void foobar(Foo.X t) {}
    };
}

不,这是不正确的。在匿名类内部,我们处于 Foo 类的作用域中,因此 Foo.X 遮蔽了外部类的类型参数 X - Landei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接