如何确保接口的未来实现也将扩展特定的类
我有一个抽象类和两个扩展它的最终类。
抽象类也是接口的实现。
现在,我必须删除两个子类之一并添加一个接口,以便人们仍然可以使用自己的实现。
但我需要确保实现新接口的人都会扩展现有抽象类。这是必需的,因为否则它将无法运行。
有没有办法实现这一点,或者我只能记录实施要求?
I have an abstract class and two final classes that extend it.
The abstract class is also an implementation of an interface.
Now I have to remove one of the two child classes and add an interface so that people can still come in with their own implementations.
But I need to ensure that whoever implements the new interface is going to extend the existing abstract class. It is required because otherwise it won't be functioning.
Is there a way to achieve that, or I can only document an implementation requirement?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
据我了解,您的目标是通过在 API 中提供单点扩展来施加限制,同时公开您的 >顶级抽象给最终用户,以便允许他们在代码中使用这些抽象。
您可以通过 Java 17 引入的密封类和接口实现对类层次结构的可访问性和控制。
已密封
该功能由 JEP 409 最终确定。
即,如果将sealed修饰符应用于类/接口,则意味着只有类或接口其声明的许可子句中列出的内容允许扩展/实施此类/接口。
permits子句需要始终出现在密封类/接口的声明中嗯>。对于其父的许可子句中提到的所有子类/子接口,它是强制扩展/实施直接父级密封。
反过来,每个子类/子接口都必须声明:
请注意,sealed 和 non-sealed 修饰符都可以与 abstract 修饰符配合使用。这对于这项任务特别有用。
实现
这一想法是创建接口(现有的且需要由最终用户实现的接口)和现有抽象类 strong>
sealed
对它们的扩展施加限制。现有的最终类别将保持为
最终
。扩展点将由
非密封
抽象类表示,它扩展了现有抽象类并实现定义用户特定行为契约的接口。通过这种方法,您可以防止
Base
接口 和Root< 定义的关键行为 /code> 类被实现在这是不受欢迎的方式,即使用
final
修饰符在OpenChild
class 中标记这些方法。同时为用户特定的行为提供一个契约,所有自定义类都应遵守该契约。这就是它在代码中的样子:
替代方案
如果您使用的是早期版本的Java,因此无法利用密封功能,那么不幸的是,您需要制作< em>在控制顶级抽象扩展的能力和最终用户可访问这些抽象的能力之间进行选择。
作为部分解决方案,您可以向最终用户隐藏除了现有的最终类
ClosedChild
和扩展点之外的所有内容强>OpenChild
。为此,上面提到的所有类和接口都必须驻留在单独的包中。 类
OpenChild
和ClosedChild
必须标记为public
。 接口基
、外部
和抽象类根
必须是< strong>package private,即它们对OpenChild
和ClosedChild
可见,但它们的行为可以从任何地方访问。注意:在
基
抽象类中声明的方法必须是public,接口中的所有方法默认都是public的,甚至接口本身也是私有的。
JDK 中这种方法的一个示例是包私有抽象类
AbstractStringBuilder
,它不可公开访问。它的public final
子类StringBuilder
和StringBuffer
共享其行为。As I understand, your goal is to impose restrictions by providing a single point of extension in your API and at the same time expose your top-level abstractions to end-users in order to allow them to utilize these abstractions in the code.
You can achieve both accessibility and control over the class hierarchy with sealed classes and interfaces introduced with Java 17.
Sealed
The feature was finalized by JEP 409.
I.e. if sealed modifier is being applied to a class/interface it implies that only classes or interfaces listed in the permits clause of its declaration are allowed to extend/implement this class/interface.
The permits clause needs to be always present in the declaration of a sealed class/interface. And for all subclasses/subinterfaces mentioned in the permits clause of their parent it's mandatory to extend/implement the sealed the parent directly.
In turn, every subclass/subinterface has to be declared either:
Note that both sealed and non-sealed modifiers play well with abstract modifier. Which is particularly useful for this task.
Implementation
The idea is to make both interfaces (existing and the one that needs to be implemented by the end-user) and existing abstract class
sealed
to impose restrictions on their extension.Existing final class will remain to be
final
.The extension point will be represented by a
non-sealed
abstract class, which extends the existing abstract class and implements the interface that defines a contract for user-specific behavior.With this approach, you can prevent the critical behaviour defined by the
Base
interface andRoot
class from being implemented in an undesired way, by marking these methods inside theOpenChild
class withfinal
modifier. And at the same time provide a contract for user-specific behavior which all custom classes are expected to conform to.That how it might look in the code:
Alternatives
If you are using an earlier version of Java and therefore can't utilize sealed feature, then unfortunately you need to make a choice between the ability to control the extension of your top-level abstractions and accessibility of these abstractions to the end-users.
As a partial solution, you can hide from the end-user everything apart from the existing final class
ClosedChild
and extension pointOpenChild
.In order to do that, all the classes and interfaces mentioned above have to reside in a separate package. Classes
OpenChild
andClosedChild
must be marked aspublic
. InterfacesBase
,Outer
and abstract classRoot
have to be package private, i.e. they will be visible toOpenChild
andClosedChild
, but their behaviour will accessible from everywhere.Note: methods declared inside the
Base
abstract class in order to make them assemble to the end-user must bepublic
, all methods in interfaces are public by default even the interface itself package private.An example of this approach in the JDK is a package private abstract class
AbstractStringBuilder
, which is not publicly accessible. And itspublic final
subclassesStringBuilder
andStringBuffer
share its behaviour.