java 接口 final_为什么Java 8接口方法中不允许"final"?

Brian Goetz..

402

理解默认方法的关键是主要设计目标是界面演化,而不是"将界面转换为(平庸)特征".虽然两者之间存在一些重叠,但我们试图适应后者,但它并没有妨碍前者,从这个角度来看,这些问题最好被理解.(另请注意,由于接口方法可以多次继承,因此无论意图如何,类方法都将与接口方法不同.)

默认方法的基本思想是:它是具有默认实现的接口方法,派生类可以提供更具体的实现.并且因为设计中心是接口演化,所以默认方法能够以源兼容和二进制兼容的方式添加到接口之后是一个关键的设计目标.

对"为什么不是最终默认方法"的简单回答是,然后主体将不是简单的默认实现,它将是唯一的实现.虽然这个答案有点过于简单,但它给我们提供了一个线索,即问题已经朝着可疑的方向发展.

最终接口方法可疑的另一个原因是它们为实现者创建了不可能的问题.例如,假设你有:

interface A {

default void foo() { ... }

}

interface B {

}

class C implements A, B {

}

一切都很好; C继承foo()自A.现在假设B已更改为具有foo默认值的方法:

interface B {

default void foo() { ... }

}

现在,当我们去重新编译时C,编译器会告诉我们它不知道要继承什么行为foo(),所以C必须覆盖它(A.super.foo()如果它想要保留相同的行为,可以选择委托.)但是如果B已经默认final,并且A不受作者的控制C?现在C已经无可挽回地破裂了; 如果没有覆盖它就无法编译foo(),但foo()如果它是最终的,则无法覆盖B.

这只是一个例子,但关键是最终方法实际上是一个在单继承类(通常将状态与行为耦合)的世界中更有意义的工具,而不是仅仅贡献行为并且可以多次继承的接口.很难推断出"其他接口可能会混入最终的实现者",并且允许接口方法最终可能会导致这些问题(并且它们不会在编写接口的人身上爆炸,而是在试图实现它的穷人.)

不允许他们的另一个原因是他们不会意味着你认为他们的意思.仅当类(或其超类)不提供方法的声明(具体或抽象)时,才考虑默认实现.如果默认方法是final,但是超类已经实现了该方法,则默认值将被忽略,这可能不是默认作者在声明最终时所期望的.(这种继承行为反映了默认方法的设计中心 - 接口演化.应该可以将默认方法(或现有接口方法的默认实现)添加到已经具有实现的现有接口,而无需更改实现接口的现有类的行为,保证在添加默认方法之前已经工作的类将在存在默认方法时以相同的方式工作.)

很高兴看到你回答有关新语言功能的问题!在确定*我们应该如何使用新功能时,澄清设计的意图和细节非常有帮助.参与设计的其他人是否也为SO做出了贡献 - 或者您自己就是这样做的?我将在java-8标签下关注你的答案 - 我想知道是否还有其他人这样做,所以我也可以关注它们. (87认同)

@Trying Abstract类仍然是引入状态或实现核心Object方法的唯一方法.默认方法是*纯行为*; 抽象类用于与状态相结合的行为. (15认同)

@Shorn [Stuart Marks](http://stackoverflow.com/users/1441122/stuart-marks)已经在java-8标签中处于活动状态.[Jeremy Manson](http://stackoverflow.com/users/2189686/jeremy-manson)已发布过去.我还记得看到来自Joshua Bloch的消息但现在找不到它们. (10认同)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值