Java 使一个类在运行时扩展另一个类

Java 使一个类在运行时扩展另一个类,java,class,inheritance,runtime,extends,Java,Class,Inheritance,Runtime,Extends,有一个库有一个基类(我们称之为CBase)来执行一些任务,可以创建扩展这个CBase类的类 CBase的行为对我来说还不够,所以我想创建自己的CBase类(我们称之为MyCBase),它具有相同的方法和成员,但这些方法做的事情不同 直到现在一切都很好。但阻碍我的是,我想用MyCBase替换CBase。然而,我有很多扩展CBase的类,我不想全部更改它们 是否可以在运行时用MyCBase替换CBase? 所以 变成 public class A extends MyCBase {} 我可以使用代

有一个库有一个基类(我们称之为CBase)来执行一些任务,可以创建扩展这个CBase类的类

CBase的行为对我来说还不够,所以我想创建自己的CBase类(我们称之为MyCBase),它具有相同的方法和成员,但这些方法做的事情不同

直到现在一切都很好。但阻碍我的是,我想用MyCBase替换CBase。然而,我有很多扩展CBase的类,我不想全部更改它们

是否可以在运行时用MyCBase替换CBase? 所以

变成

public class A extends MyCBase {}
我可以使用代码增强来执行此操作吗?(就像我们在运行时向类添加方法一样。也可以这样更改继承吗?)

谢谢你的帮助

编辑

我想为框架编写一个插件,这就是为什么我想在运行时更改继承。这样,框架用户就可以使用my plugin,而无需更改源代码(将类的继承从CBase更改为MyCBase)

编辑2

可以这样做吗:

CtClass cc = CtClass.forName("pkg.AClass");
cc.setSuperclass(CtClass.forName("mylib.MyCBase"));
cc.compile();

我不是专家。可能您可以扩展
类加载器
。但我强烈建议不要这样做。替换将涉及到您的许多类,但在代码读取和应用程序执行方面会很清楚


我认为体系结构也有改进的余地,因为有太多类扩展了
CBase
。人们正试图从其他库中删除依赖项,或者使其非常小。因为在这种情况下,您可以轻松切换到另一个库或添加自己的功能。

我认为您无法在运行时更改类的扩展。我建议更改对象的扩展或构建一个接口,该接口包含您需要的所有内容

更改所有派生类很简单,只要您控制它们的源代码:

  • 在项目中创建一个新类。将其命名为CBase,并将其与库类放在同一个包中
  • 使用IDE的重命名/移动重构将CBase重命名为MyBase。这将使IDE重命名重命名/移动类的所有引用
  • 为MyBase编写代码,从CBase扩展而来
  • 如果您不能做到这一点(例如,因为某些派生类位于不受您控制的库中),则可以用自己的实现替换CBase的实现。只需在项目中创建一个具有相同包和名称的类(类加载器按顺序搜索类路径,并使用找到的正确包和名称的第一个类)。然而,这种方法非常脆弱,因为编译器无法检查旧版本和新版本CBase之间的二进制兼容性。JVM将在加载类时检查这种兼容性,但由于类仅在需要时加载,因此很难测试您的更改。(这就是为什么如果有其他选择,我不推荐这种方法)


    您还可以在加载类时更改类,这将更加脆弱,编译器将允许您使用MyBase可能具有的任何其他功能。==>绝对不是一个好主意。

    即使你可以,这也是一个糟糕的主意。是什么阻止你简单地编辑CBase的行为?@DuncanJones我无法访问CBase的代码,因为它位于外部数据库中library@JoachimSauer为什么会这么可怕?我只想用受控类集中的MyCBase类替换CBase类你能用委托来解决你的问题吗?同样感谢您的回答,但我想做的是保留实际的源代码(类扩展CBase),这样其他开发人员就不会有任何更改(我想做的是插件的一部分)并在运行时更改继承。你的其他想法很好,但是如果可能的话,我想要一些不那么脆弱的东西。类文件的运行时操作将是脆弱的,因为编译器不会检查它,而且问题只会在运行时发现。如果您的开发伙伴在IDE中看到的代码不是执行的代码,他们也可能会发现这有误导性。我不认为他们会发现这有误导性,因为我的插件必须替换现有的插件,所以他们知道行为将被改变。你认为使用这个代码可以完成我想要的工作吗?(并编译):CtClass cc=CtClass.forName(“pkg.AClass”);cc.setSuperclass(CtClass.forName(“mylib.MyCBase”);cc.compile();这可能是一个很好的解决方案,但我想为其编写一个插件的框架已经扩展了ClassLoader,我认为我无法改变这一点
    CtClass cc = CtClass.forName("pkg.AClass");
    cc.setSuperclass(CtClass.forName("mylib.MyCBase"));
    cc.compile();