我创建了一个库,该库扩展了另一个用C++编写的库,现在我将该库移植到Java(C++最初编写的原始库已经存在于Java中)。在C++代码中,存在纯粹的虚拟类Stallable,应该使用该类,以在给定电压输入增量的情况下向电动机 Controller 添加失速检测。该类包含一个纯虚拟方法getVoltage(),用于提供电压源,因为它们是几种不同的电动机 Controller 类,还包含一些虚拟函数来确定是否存在失速。

类将继承该类以及原始库中的一个类(我不能访问该代码,并且出于所有意图和目的,否则将无法对其进行修改),并将实现getVoltage(),并覆盖任何其他方法他们可能会喜欢。然后可以仅询问这些对象是否存在停顿。

当我从Java的 Angular 解决这个问题时,我的处境变得更加棘手。我仍然无法接触原始类,因此无法重构代码,并且仍然允许我库的用户子类化或实现Stallable,但他们认为合适。

目前,我看到的前景如下。

  • Stallable设置为接口(interface),并重新实现其使用的停顿检测逻辑。为了创建C++代码库具有的原始功能,我必须让类继承原始库并实现Stallable。这会起作用,但是需要在我要包含的任何子类中以及最终用户要编写的任何子类中重新实现原始的纯虚拟C++ Stallable中的逻辑。
  • 使Stallable为抽象类,该抽象类包含对原始库中电动机 Controller 类的对象引用。这保留了C++代码中的某些功能,因此某些方法将必须被覆盖,而某些方法则可以选择性地被覆盖,但是此代码与C++代码之间的透明度丢失了。在C++中,由于每个子类都是一个Stallable,并且是原始马达 Controller 的派生类,因此在需要马达 Controller 和需要Stallable对象时,很容易将指针扔向该对象。在这种情况下,必须实现某种类型的访问器函数,该函数将Java引用返回到每个Stallable子类将保留的原始电机 Controller 。透明度会丢失,但很容易添加停顿检测。

  • 显然,如果我可以为各种电机 Controller 修改原始类,则此问题很容易是重构C++代码的问题。

    在研究了两种语言的OOP方法之间的差异之后,我倾向于选择选项2,尽管它给最终用户和计划包括的Stallable实现增加了摩擦。在开始编写Stallable.java之前,我一直在问是否还有其他更好的想法或见解。

    最佳答案

    因此,基本上,您想要的是lib的Java用户能够实现接口(interface),并且行为会随之发生?这听起来像是AOP(面向方面​​的编程)的工作。使用AOP(例如,AspectJ),您可以将方法注入(inject)符合特定条件的类。

    在您的情况下,标准是“实现Stallable接口(interface)”。 AOP的问题在于它是侵入性的。如果您选择进行运行时编织,则用户将需要使用AOP编译其类或将AOP添加到其类路径中。

    另一种选择是尝试使用动态代理进行一些委派。

    最后,您可以尝试使用字节码操作http://asm.ow2.org/以便在运行时生成类。

    如果您编写一个有关Java代码外观的示例,也许我的答案可能不太明确。

    08-26 19:51