【问题标题】:Adding functions to Java class libraries向 Java 类库添加函数
【发布时间】:2010-05-03 21:01:17
【问题描述】:

我使用的 Java 类库在许多方面都不完整:有很多类我觉得应该内置额外的成​​员函数。但是,我不确定添加这些成员函数的最佳实践。

让我们调用不足的基类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,所以不能向下转换。

那么将成员函数添加到只读库类的最佳方法是什么?

【问题讨论】:

  • @Eric:通常在 Java 中,函数被称为“方法”,即使它们是函数 :)

标签: java function casting class


【解决方案1】:

自然而频繁的困境。阅读composition vs inheritance 替代方案。您的第二种选择基本上是组合,如果我们认为对象 A 在构造函数中传递而不是在每个方法中传递 - 也就是说,我们将使用组合来实现 wrapper 或 @987654322 @ 模式。

C 类返回 A 类的新实例的问题没有简单的解决方案,正如您所猜测的,只要 C 类决定承担创建新实例的责任。这就是为什么在类中键入“新”语句之前应该暂停并思考一下,如果这个类有可能被子类化。在您的示例中,如果您可以告诉 C 类要返回哪个具体类,那就太好了……但是它怎么知道要创建它呢?好吧,我们可以传给他一个知道如何实例化 A 类(或子类)对象的对象......我想你现在有足够的动力去阅读 Factories 以及一般的设计模式。

没有唯一的最佳答案,但如果想要一个快速的答案:我会做一个包装器,B 类不扩展 A,但有一个以 A 作为参数的构造函数,它将其方法(除了自己的)委托给内部对象。 当你需要调用 C 类中的方法时(我假设你不能接触 C 类),你可以写:B b = new B(c.func())

【讨论】:

  • 我接触 C 类的唯一方法是从它派生另一个修改后的类,这样做很快就会使代码不可读。有没有一种简单的方法可以让B 扩展A,并给它一个以A 作为参数的构造函数?
  • 不,你在这里混合了一些东西(准确地说是组合和继承)。继承和装饰器(由组合实现)以及您可以“触摸”一个类的两种替代方式(即向其添加行为状态)。如果您阅读过它,您会发现继承经常被 OOP 新手高估。
【解决方案2】:

为什么不使用组合而不是继承?

class ABetterA {
    private A a;

    public ABetterA() {

    }

    // write wrapper methods calling class' A methods and maybe doing something more
}

这样,您还可以模拟多重继承...

【讨论】:

    【解决方案3】:

    你有第三种选择。您可以使用 Scala(一种 Java 兼容语言)及其 traits,也就是 mixins 的另一个名称。

    【讨论】:

    • 不幸的是,我没有那个选项。我正在为机器人平台 (LeJOS NXJ) 使用 Java 子集。
    【解决方案4】:

    另一个类似于 Brian 建议的选择是使用 Aspect Oriented Programming (AOP) 工具,例如 ApectJ,它可以让您将附加功能“注入”到现有类中,甚至是二进制的。您可以预处理库 jar 以获得具有增强类的新 jar(“静态编织”),或者您可以在加载库类时在运行时执行所有这些操作(所谓的“加载时编织”)。您可以查看此AspectJ example

    尽管 AOP 通常用于修改现有方法(“建议”= 代码片段之前、之后或前后),但您也可以引入新成员和方法 - 检查 AspectJ's Inter-type declarations

    当然还有一个问题是你的有限平台是否支持 AspectJ。

    【讨论】:

      猜你喜欢
      • 2023-03-17
      • 2017-02-11
      • 2019-01-28
      • 2016-06-15
      • 2019-05-17
      • 2019-12-07
      • 2015-07-15
      • 2019-12-29
      • 1970-01-01
      相关资源
      最近更新 更多