为什么接口无法标记为密封的?

26
public sealed interface IMyInterface
{
}

显示“此项不允许使用修改后的 'sealed'”

我可以理解接口必须是可以派生的,否则类无法实现该接口。

但为什么我不能指定一个接口不应该有子接口定义呢?或者说是否有另一种方法能够实现这个功能,只是不用sealed关键字而已?

编辑

我应该努力解释一下为什么我需要这个。我经常看到接口继承链,而开发人员应该使用组合。在类中,sealed非常适合此类情况,因此我想知道是否有一种方法可以强制接口也遵循这样的规则。我认为,不必要的继承会使重构和维护变得更加困难。

编辑2

考虑到评论和帖子,接口继承树不可能像对象继承树那样复杂。因为当你从另一个接口IX派生时,你所说的只是“还必须实现IX”。禁止这样做没有任何好处。


你会用这个做什么?你的意思是你希望一个sealed接口可以被继承,但是继承类不能创建新的成员函数吗?还是其他什么意思? - Mr Lister
1
@MrLister:我能想到的唯一可能有些意义的意思是,防止接口从接口派生。 - George Duckett
既然这是我第一次看到这个问题出现,我认为以前没有人需要过这个功能,这也立即回答了你的问题:没有人实现这个功能,因为迄今为止还没有人需要它 :-) - Steven
2
我同意你的观点,韦斯顿。类继承和接口实现之间有明显的区别。如果一个接口被封闭,那对我来说意味着你不能派生一个接口,但这并不意味着在类中实现它会有任何不同。继承和实现是两个不同的概念。 - Brad Rem
8个回答

30

封闭类或类的虚方法的目的是降低成本。为继承设计是昂贵的,而且如果您没有正确地做好,这是危险的。不正确地为继承设计会带来安全性、正确性和稳健性问题,因此,如果您不打算为继承设计,请明智地封闭您的类,以避免与为继承设计相关的成本。

类需要为继承设计,因为它们具有实现细节。接口没有实现细节。允许接口被继承不会产生任何成本。因此,没有激励添加允许接口被封闭的功能。


1
通过限制接口继承链,重构和维护是否没有成本效益? - weston
2
@ShuggyCoUk:如果一个接口被定义为internal,有没有一种类型安全的方式将实例传递给外部代码,并让它们将其传回?考虑这样的情况,类UsCheckingAccount是从UsBankAccount派生而来的,而FrenchCheckingAccount是从FrenchBankAccount派生而来的,它们都在一个程序集中。我想定义一个ICheckingAccount,它可以是其中任何一个,但是希望接受ICheckingAccount的代码知道它实际上是其中之一,而不是其他任意的类。(是的,我知道,类继承并不能提供真正的安全性)。 - supercat
1
@GlennSlayden “标记”类似于属性的作用,而不是接口。 - Dave Cousineau
@EricLippert 说“接口没有实现细节”这并不完全正确,因为在 Kotlin 中,接口可以有已实现的方法。 - David Aleksanyan
1
这个问题是关于C#而不是Java或Kotlin的。然而,C#很快就会获得带有实现的接口,因此答案需要更新。 - Eric Lippert
显示剩余7条评论

14

这样做只会让人更加困惑。使用标准语法,这将意味着您无法实现接口。而且,接口不包含任何功能或字段,因此封闭它是没有实际用途的。接口更多地是一个合同。

对于“接口继承”封闭接口并没有什么作用,因为人们可以实现你的接口和那个已经继承了你的接口的接口。


5
在接口的上下文中,“sealed”意味着没有类可以实现该接口。这是无用的,因此不允许这样做。

1
接口是否可以从一个接口派生出来呢?我能理解从那个角度来看 sealed 可以有意义。然而,除了不从这样的限制中获得任何好处外,可能还有其他原因使其不合理。 - George Duckett

1

0

Sealed 是一个类的关键字。接口的目标是让类实现它们定义的任何合同。您可以封闭实现接口的类,但封闭接口没有什么用处。


0

接口是您的应用程序合同...当您不需要您的合同时,为什么要定义它?


0
封装类的主要目的之一是要求该类的所有存储位置只能保存该精确类型的实例,而不能保存派生类型的实例。尽管大多数代码不会介意将派生类型对象替换为基类型对象,但在许多情况下,这种替换可能会带来问题。例如,某些类包含一个函数,用于与同一类型的另一个对象进行相对比较,并期望比较结果能产生一个可排序的序列。如果类型Bar和Boz都派生自Foo,并且在比较中使用了任何Bar特定或Boz特定的字段,那么在持有混合Bar和Boz实例的序列中进行有意义的排序可能是不可能的。
这样的目的在接口中并不存在,因为按照它们的本质,接口被设计成可由多个类实现。一个不能被任何类实现的接口是没有用处的,而一个只能由一个类实现的接口也是无意义的(如果IFoo除了Foo之外别无选择,那么在任何需要使用IFoo的地方都可以简单地使用Foo)。

将接口的实现限制为定义它的模块以及允许接口具有内部成员可能会有一定的用处。 我不知道为什么不允许这样做,甚至不知道允许或禁止此类事情是否比禁止它们更容易或更难。


-1
对我来说,interface 暗示着一个 abstract 关键字;因此,如果一个接口被 sealed 修饰,它将会是 sealed abstract,这似乎是一种矛盾。

1
FYI,“静态”类在逻辑上既是sealed又是abstract的;您不能从中继承,也不能创建实例。 - Eric Lippert
1
谢谢,Eric。和编译器开发人员争论总是让我感到非常渺小和幼稚 :-) - Uwe Keim

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