在 Java 中,我定义了一个包含具体方法和抽象方法的抽象类,并且它必须由第三方开发人员独立地进行子类化。只是为了确定:我可以对抽象类进行任何与它们的类源兼容但不兼容二进制的更改吗?换句话说:在他们编译了他们的子类之后,我可以改变抽象类吗?这可能会迫使他们重新编译他们的子类?
3 回答
如果现在更改系统还为时不晚,我建议您这样做。覆盖通常不是自定义功能的好方法,因为它非常脆弱。例如,如果您稍后使用您的客户使用过的方法名称(他们现在无意中自动覆盖),那么覆盖可能会完全破坏您的类的不变量。提供定制的一种通常更好的方法是给你的客户一个仅限于定制行为的接口,然后你有一个完全具体的类,它依赖于这个接口的一个实例,并在需要时适当地委托给接口使用自定义的行为。这样一来,你的代码和你客户的代码就完全分离了,不会互相干扰。
我假设您在技术意义上使用“二进制不兼容”;例如,类加载器检测到不兼容并拒绝加载类。
如果您添加一个可见方法并声明它final
,并且该方法与第三方子类中某些现有方法的签名相冲突,也可能会引入二进制不兼容。但是,如果该方法不是最终方法,则现有方法将变成您的(新)方法的覆盖,这可能会导致问题......但不会导致二进制不兼容。
同样,添加新的可见字段会导致隐藏,可能会导致混乱的行为并会破坏对象序列化。但这不会导致二进制不兼容。
一般来说,这表明您需要考虑应用程序语义问题以及简单的二进制兼容性。Java 类型系统在这方面帮不了你。
为了完整起见,您可以在代码中执行其他一些操作,这些操作会破坏 3rd 方类的二进制兼容性:
- 降低抽象类和/或其方法的可见性,
- 更改用作参数结果和异常类型的其他类的签名,
- 更改抽象类扩展的超类链,或对这些类进行不兼容的更改,或
- 更改抽象类实现的接口树,或在这些接口中进行不兼容的更改。
当然。
您可能会不小心使用了他们曾经使用过的方法名称,该名称现在突然被覆盖,可能会产生截然不同的结果。
您可以将字段添加到混淆序列化等的类中。