扩展用Java实现接口的三个类



我使用一个带有接口的库,IFC,该接口由a、B和C三个类实现。

我想自己实现方法M,它在IFC中定义,并在A、B和C中实现,它应该覆盖A、B、C中的相应方法。

这可能吗?

在Java中,实现,而不是扩展接口,并且只能扩展一个类。这让我得出结论,我想做的事情是不可能的。

相反,我需要创建:

class MyA extends A {
myM () {
// Do my stuff
super.M();
}

然后是B和C的两个相同的类,每个类都有一个相同的myM方法,但这感觉真的很笨拙和丑陋。还有别的办法吗?

使用此库的简化实现,使用method()而不是M():

interface IFC {
void method();
}
class A implements IFC {
public void method() {
System.out.println("method in A");
};
}

正如akuzminykh在他们的评论中提到的那样

您可以编写一个具有M和IFC字段的类。在M中,你可以做你的事情,然后调用IFC的M,其中IFC可以是A、B或C。所以你可以将A、B和C的所有实例封装在这样的类中,这将避免扩展A、B、C。

这样做的好处是,您只需要在初始化类时通过包装它们来考虑它:IFC wrapIFC = new IFCWrapper(new A());。一旦完成,您就不需要像处理任何用new A():初始化的变量一样处理变量wrapIFC

class IFCWrapper implements IFC {
IFC ifc;
IFCWrapper(IFC ifc) {
this.ifc = ifc;
}
public void method() {
always();
ifc.method();
}
void always() {
System.out.println("wrapper method");
}
}

您还可以创建一个单独的独立(抽象?(类或接口,您可以调用它,而不是调用实例中传递的method()。缺点是,每次您想在实例上调用method()时,都必须记住调用此函数。我选择了使用Runnable:传递任何我想要的额外内容的选项

class IFCExt {
static Runnable defaultRun = () -> System.out.println("default extra");
static void method(Runnable toRun, IFC ifc) {
toRun.run();
ifc.method(); 
}
}

两种变体的示例运行:

public class Test {
public static void main(String[] args) { 
IFC wrapIFC = new IFCWrapper(new A());
wrapIFC.method();
System.out.println();
IFC myIFC = new A();
IFCExt.method(IFCExt.defaultRun, myIFC);
IFCExt.method(() -> System.out.println("anything extra"), myIFC); // anything you'd want
}
}

打印:

wrapper method
method in A
default extra
method in A
anything extra
method in A

我以前遇到过这样的情况。虽然代理/适配器是很好的,如果你只想在库外部使用A、B和C,那么当在内部使用时,你可能也想替换从A、B、C调用的M((。

我遇到的例子是一个使用非线程安全集合的遗留库,您只想切换它。我假设情况与我的类似,您只能访问一个jar,但没有源代码,并且您还想更改M((的内部用法。在这种情况下,正如许多人指出的那样,通过常规java代码实现这一点是不可能的。

然而,如果代码在您的计算机上,则有两种技术超出了正常java开发的范围,您可以使用。它们的利用率可能会对构建复杂性和您正在编写的代码的维护产生巨大影响。

如果您真的想在不创建自己的类的情况下替换M((的每个实例,那么一个可能的解决方案是在运行时交换方法。

有些图书馆声称能够做到这一点。这个问题详细介绍了这项技术,并重点介绍了一个可以做到这一点的库HotSwapAgent。

另一种解决方案是对库的jar进行反编译,更改有问题的方法并重新编译。根据库对其他依赖项的使用和构建复杂性,这可能不是一件小事。然后,您也处于这样一种情况,即您必须维护那个新修改的罐子。如果库更新,则必须重复此过程。

相关内容

最新更新