繁体   English   中英

为什么我不能将类型参数添加到覆盖方法?

[英]Why can't I add a type parameter to an overriding method?

我需要在我的子类Bar中从 class Foo实现一个方法:

class Foo {
    public abstract void foo();
}

class Bar extends Foo {
    
    private <T> Map<T, List<T>> getStuff() { ... }

    @Override
    public void foo() {
        Map<?, List<?>> stuff = getStuff();
        for (Entry<?, List<?>> e : stuff.entrySet()) {
            Object key = e.getKey();
            List<?> lst= e.getValue();
            lst.add(key);  // illegal: need ?, got Object
        }
    }
}

如您所见,我的方法将受益于类型参数:

@Override
public <T> void foo() {
    Map<T, List<T>> stuff = getStuff();
    for (Entry<T, List<T>> e : stuff.entrySet()) {
        T key = e.getKey();
        List<T> lst= e.getValue();
        lst.add(key);  // legal!
    }
}

(我也可以使用原始类型,因为我知道它会起作用,但我读过的所有内容都说你真的不应该这样做)

不幸的是,这是非法的——我在Bar中的方法foo “与 Foo 中的 foo() 冲突;两种方法具有相同的擦除,但都没有覆盖另一个”。

这看起来很奇怪,因为我的类型参数不会改变foo的参数或返回类型 - 任何可以使用Foo.foo的地方,也可以使用我的(非法) Bar.foo

到目前为止,我对解决方法的丑陋黑客一直只是编写一个全新的(参数化)方法:

public void foo() {
    realFoo();
}

private <T> void realFoo() {
    // parameterized version of .foo() above
}

我有两个问题:

  1. 为什么向方法添加类型参数会阻止它覆盖其超类中的未参数化方法?
  2. 有没有更好的方法来获得我想要的行为?

JLS 8.4.2

8.4.2. 方法签名

如果两个方法或构造函数 M 和 N 具有相同的名称、相同的类型参数(如果有)(第 8.4.4 节),并且在将 N 的形式参数类型调整为类型参数之后,则它们具有相同的签名的 M,形参类型相同。

方法 m1 的签名是方法 m2 签名的子签名,如果:

  • m2 与 m1 具有相同的签名,或
  • m1 的签名与 m2 签名的擦除(第 4.6 节)相同。

如果 m1 是 m2 的子签名或 m2 是 m1 的子签名,则两个方法签名 m1 和 m2 是覆盖等效的。

因为类型参数是方法签名的一部分,所以不能在覆盖方法中添加或删除类型参数。

我丑陋的解决方法...

是的,这很丑陋,但这是正确的做法。

暂无
暂无

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

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