关于Java子接口子类型
这似乎是一个基本的java问题 我有一个接口,关于Java子接口子类型,java,interface,Java,Interface,这似乎是一个基本的java问题 我有一个接口,Pipeline,它有一个方法execute(Stage) 然后我创建一个子接口来扩展管道,比如说BookPipeline,我喜欢方法是execute(BookStage) BookStage扩展自Stage 这种定义似乎无法通过java编译 有什么建议吗? < P>你可能想考虑使用泛型。 public interface Pipeline<T extends Stage> { public void execute(T sta
Pipeline
,它有一个方法execute(Stage)
然后我创建一个子接口来扩展管道
,比如说BookPipeline
,我喜欢方法是execute(BookStage)
BookStage
扩展自Stage
这种定义似乎无法通过java编译
有什么建议吗? < P>你可能想考虑使用泛型。
public interface Pipeline<T extends Stage> {
public void execute(T stage);
}
public interface BookPipeline extends Pipeline<BookStage> {
@Override
public void execute(BookStage stage);
}
公共接口管道{
公开无效执行(T阶段);
}
公共接口管道扩展了管道{
@凌驾
公开作废执行(BookStage阶段);
}
除了@Jeffrey所写的可能的解决方案之外,理解您为什么不能这样做也很重要
假设您有一个带有方法execute(Stage)
的接口Pipeline
,以及一个带有execute(BookStage)
的扩展接口BookPipeline
还假设您有一个类Conc
,它实现了BookPipeline
考虑以下几点
Pipeline p = new Conc();
p.execute(new Stage());
会发生什么?这是不安全的!
Java希望避免这种情况,因此从一开始就避免了这种情况
规则是,扩展类/接口可以添加行为,但不能减少它仅就@amit的答案进行详细说明,代码片段是不安全的,因为
Conc.execute
方法将BookStage
作为参数,这将试图压缩一个阶段
(当然,并非所有的Stage
s都是BookStage
s)
但是,假设我们想走另一条路,也就是说,将BookEpiLine.execute
的参数类型设为Stage
的超级类型,例如Object
因此,为了澄清,我们将:
interface Pipeline
{
void execute(Stage s);
}
interface BookPipeline extends Pipeline
{
@Override
void execute(Object s);
}
其中Conc
实现BookPipeline
:
Pipeline p = new Conc();
p.execute(new Stage());
从理论上讲,这是安全的,因为Liskov可替换性没有被违反-我们可以安全地将阶段
传递到任何采用阶段
参数或更大参数的实现中。这称为逆变。Java不支持逆变参数类型,但也有支持逆变参数类型的
您最初的问题与协变参数类型有关,由于指定的原因,协变参数类型是不安全的(不管多么奇怪,一种称为的语言允许这样做)
但是Java支持协变返回类型
Stage getAStage();
BookPipeline
这样覆盖此方法是完全合法的:
@Override
BookStage getAStage();
然后想象我们有:
public void someMethodSomewhere(Pipeline p)
{
Stage s = p.getAStage();
//do some dance on Stage
}
假设我们有一个类Donc
,它实现了Pipeline
,并完全按照Pipeline
中的定义重写了getAStage()
(因此仍然返回Stage
),这两个调用都可以:
someMethodSomewhere(new Conc());
someMethodSomewhere(new Donc());
因为我们总是可以在类型为Stage
的变量中放置Stage
或任何更小的内容(例如BookStage
)
因此,为了将规则改写为专门与方法重写相关,重写方法的扩展类/接口只能使这些方法在接受的内容上更加通用,在返回的内容上更加具体。(尽管在Java中,只允许使用更具体的返回类型。)
请记住,PECS-Producer Extends,Consumer Super(约书亚·布洛赫,高效Java)编译器错误消息是什么?你的代码是什么?执行的声明不是在
BookPipline
redudant中吗?@KirkWoll是的,它是为了示例而存在的,我不需要重写它。非常感谢!