我使用的Java类库在很多方面都是不完整的:我觉得应该有许多类内置其他成员函数。但是,我不确定添加这些成员函数的最佳实践。< / p>
让我们调用不充分的基类A
。
class A
{
public A(/*long arbitrary arguments*/)
{
//...
}
public A(/*long even more arbitrary arguments*/)
{
//...
}
public int func()
{
return 1;
}
}
理想情况下,我想向A
添加一个函数。但是,我做不到。我的选择是:
class B extends A
{
//Implement ALL of A's constructors here
public int reallyUsefulFunction()
{
return func()+1;
}
}
和
class AddedFuncs
{
public static int reallyUsefulFunction(A a)
{
return a.func()+1;
}
}
我看待它的方式,它们都有优点和缺点。第一种选择提供了比第二种选择更清晰的语法,并且更符合逻辑,但存在问题:假设我在类库中有第三个类C
。
class C
{
public A func()
{
return new A(/*...*/);
}
}
正如我所看到的,没有简单的方法可以做到这一点:
C c;
int useful = c.func().reallyUsefulFunction();
由C.func()
返回的类型为A
,而不是B
,您无法向下投射。
那么将成员函数添加到只读库类的最佳方法是什么?
答案 0 :(得分:2)
为什么不使用Composition而不是Inheritance?
class ABetterA {
private A a;
public ABetterA() {
}
// write wrapper methods calling class' A methods and maybe doing something more
}
这样,你也可以模仿多重继承...
答案 1 :(得分:2)
自然而频繁的困境。阅读composition vs inheritance替代方案。如果我们认为对象A在构造函数中传递而不是在每个方法中传递它,那么你的第二个选择基本上是一个组合 - 也就是说,我们将使用组合来实现包装器或{{ 3}}模式。
只要C类决定承担创建新实例的责任,C类返回A类新实例的问题就没有任何简单的解决方案。这就是为什么在类中键入“new”语句之前应该暂停和思考的原因,如果有可能将该类子类化。在你的例子中,如果你能告诉C类要返回的具体类,那将会很好......但是如何创建它呢?好吧,我们可以向他传递一个知道如何实例化A类(或子类)对象的对象......我猜你现在已经足够有动力阅读decorator,并且通常会设计模式。
没有唯一的最佳答案,但如果想要一个快速的答案:我做一个包装器,B类不扩展A但是有一个带有A作为参数的构造函数,它将其方法(除了自己的)委托给内部对象。
当你需要在C类中调用该方法时(我假设你无法触及C类),你可以写:B b = new B(c.func())
答案 2 :(得分:1)
答案 3 :(得分:0)
类似于Brian的另一个选择是使用面向方面编程(AOP)工具,例如 ApectJ ,它可以让您在现有类中“注入”其他功能,甚至是二进制的。您可以预处理库jar以获取具有增强类的新库(“静态编织”),也可以在加载库类时在运行时执行所有这些操作(所谓的“加载时编织”)。您可以查看AspectJ example。
即使AOP通常用于修改现有方法(在“建议”之前,之后或周围=代码片段),您也可以引入新成员和方法 - 检查AspectJ's Inter-type declarations。
当然,在您的有限平台上是否支持AspectJ存在问题。