4

这段代码有什么问题?

public interface FileProccessor {
    public <RT> RT setHeader(RT header);
}

public class AProcessor implements FileProccessor {

    @Override
    public Header setHeader(Header header) {
        return null;
    }
}

编译器抱怨:AProcessor 类型的方法 setHeader(Header) 必须重写或实现超类型方法

编辑: 谢谢。我很困惑,因为我想要多种不同类型的方法。现在我意识到可以在类级别添加任意数量的参数化类型。喜欢FileProcessor<T, F, M>

4

5 回答 5

4

您的接口声明指定接口的所有实现都将提供具有此签名的通用方法:

public <RT> RT setHeader(RT header);

换句话说,调用者将能够传递任何类型的对象,并返回相同类型的对象。

另一方面,您的实现声明将用户限制为单一类型,即Header. 这就是编译器抱怨无法覆盖的原因。

如果接口是泛型的,并且实现它的类型正在实现泛型实例,则该技巧将起作用,如下所示:

public interface FileProccessor<T> {
    public T setHeader(T header);
}

public class AProcessor implements FileProccessor<Header> {
}
于 2012-09-28T10:05:45.967 回答
3

我想你想这样做:

public interface FileProccessor<RT, RX> {
    public RT setHeader(RT header);
    public RX setFooter(RX footer);
}

public class AProcessor implements FileProccessor<Header, Footer> {

    @Override
    public Header setHeader(Header header) {
        return null;
    }

    @Override
    public Footer setFooter(Footer footer) {
        return null;
    }
}
于 2012-09-28T10:03:44.370 回答
1

尝试像这样定义你的界面:

public interface FileProccessor<RT> {
    public RT setHeader(RT header);
}

然后像这样实现它:

public class AProcessor implements FileProccessor<Header> {
    @Override
    public Header setHeader(Header header) {
        return null;
    }
}
于 2012-09-28T10:04:10.190 回答
0

您不能以这种方式覆盖方法。AProcessor必须能够接受所有FileProcessor接受作为setHeader. 考虑这段代码:

FileProcessor f = new AProcessor();
String s =  f.setHeader("Bah");

无论使用哪个具体类,此代码都应该可以工作,并且它不适用于您的AProcessor. 因此,类型检查器拒绝它是有道理的。

这样的事情会起作用(因为 FileProcessor 接口现在用 RT 参数化了):

public interface FileProccessor<RT> {
    public RT setHeader(RT header);
}

public class AProcessor implements FileProccessor<Header> {

    @Override
    public Header setHeader(Header header) {
        return null;
    }
}

现在该类的用户必须编写:

FileProcessor<Header> f = new AProcessor();

并且参数 tosetHeader必须是类型Header...

于 2012-09-28T10:06:01.193 回答
0

JLS #8.4.2。方法签名

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

  • m2 与 m1 具有相同的签名,或

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

在你的情况下erasure是不同的,即。在一次情况下,你有,而在你没有的实施类中。

因为允许原始类型覆盖下面的泛型方法可以在您的情况下工作。

    @Override
    public Object setHeader(Object header) {
        return null;
    }

此外,如果您更改您的声明如下

 public interface FileProccessor<T> {
    public T setHeader(T header);
 }

FileProccessor<T>您可以在扩展时根据子类中传入的类型覆盖方法

public class AProcessor implements FileProccessor<Header> {
    @Override
    public Header setHeader(Header header) {
        return null;
    }
}
于 2012-09-28T10:20:53.787 回答