扩展BigDecimal?

问题描述 投票:8回答:5

我使用BigDecimal Class有相当多的代码,我讨厌界面的笨拙。

通过使用以下方法创建一个带静态方法的辅助类,我减轻了使用整数使用BigDecimals的痛苦:

compare(BigDecimal first, int second)
divide(BigDecimal dividend, BigDecimal divisor, int scale)
divide(BigDecimal dividend, int divisor, int scale)
divide(int divident, int divisor, int scale)
multiply(BigDecimal first, BigDecimal second, int scale)
multiply(BigDecimal first, int second, int scale)
multiply(int first, int second, int scale)
zeroPad(BigDecimal value, int totalLength, int scale)

这就是我现在所需要的,代码比以前更具可读性。但是,我读到静态方法是一个“坏”的东西,他们不遵循OO原则。

但是,如果我扩展BigDecimal,我会定义一个新类型,因此我必须重新定义所有方法用我的对象包装它们,否则我将无法使用增强方法的结果。做起来似乎并不聪明。

你会如何解决这个问题?

java design-patterns static-methods
5个回答
5
投票

我会像你一样完成它!

此类型的所有设计决策都必须基于希望使代码更易于维护,以便下一个程序员接管您之后的代码。这就是为什么我们首先进行O-O设计和基于组件的开发。

但是考虑到Java的语法,很难为基于数学的表达式创建API。我当前的BigInteger API有两个问题:

  • 它与通常的数学符号并不十分接近
  • 它对于加法和乘法等对称运算符是不对称的

[运算符重载是C ++的少数功能之一,我想念Java]

哪个更具可读性?

BigInteger a = ...;
BigInteger b = ...;
BigInteger c = divide(a, b);

要么

BigInteger a = ...;
BigInteger b = ...;
BigInteger c = a.divide(b);

就个人而言,我更喜欢第二个版本。

更糟糕的是不同基类型的数量是同一表达式的一部分的情况。例如。

int a = ...;
BigInteger b = ...;
BigInteger c = divide(a, b);

要么

int a = ...;
BigInteger b = ...;
BigInteger c = BigInteger.valueOf(a).divide(b);

还要考虑相应数学符号中小变化的符号的巨大差异:

  • (a-b)*c被翻译为a.subtract(b).multiply(c)multiply(subtract(a,b),c)
  • c*(a-b)被翻译为c.multiply(a.subtract(b))multiply(c,subtract(a,b))

对我来说,编写和读取静态方法表示法比“纯”基于O-O的表示法更容易。


4
投票

不要扩展BigDecimal,使用它周围的包装类(就像你有)或其他框架,如Commons Math。

Dfp看起来与你想要的相似 - org.apache.commons.math.dfp.Dfp


2
投票

你能否向我澄清一下你的意思是什么?“我定义了一个新类型,因此我必须重新定义所有方法用我的对象包装它们,否则我将无法使用增强的方法。“?

  • 如果您需要使用BigDecimal API中的大多数方法,加上您自己的其他方法,那么我建议您从BigDecimal继承您的自定义类。这样,您就不需要为已经适合您的BigDecimal方法定义包装器。这种情况是您的自定义类是BigDecimal的情况,还有更多。
  • 如果您只需要BigDecimal API中的一些方法,加上您自己的其他方法,那么我建议您不要从BigDecimal派生。相反,您在内部使用BigDecimal,并将自定义API公开的一些功能委托给它。这种情况是您的自定义类具有BigDecimal的情况,但它不是BigDecimal。

然后,为了包装BigDecimal方法以返回您的自定义类型:

通过继承,您可以执行以下操作:

@Override public MyBD divide(int second)
{
    return new MyBD( this.divide(second) );
}

通过授权(即组合),您可以:

public MyBD divide(int second)
{
    return new MyBD( _innerBigDecimal.divide(second) );
}

使用静态辅助方法,您可以:

public static BigDecimal divide(BigDecimal first, int second)
{
    return first.divide(second);
}

0
投票

如果您创建一个扩展另一个类的类(例如,在您的情况下为BigDecimal),则子类仍具有父(超)类的所有属性。在你的情况下,如果你写:

public class UsableBigDecimal extends BigDecimal {
...
}

任何UsableBigDecimal对象仍然是BigDecimal的实例,因为它是它们的超类。您可以像使用任何BigDecimal对象一样使用它们,包括静态实用程序方法。

也就是说,在我看来,静态实用程序方法作为在处理核心Java类时共享公共代码的一种方式是完全可以接受的。


-4
投票

我会忘记这个问题,以及原来的问题,并习惯了BigDecimal的API。你正在做的就是为自己创造问题,因为这个问题的存在证明了这一点。

© www.soinside.com 2019 - 2024. All rights reserved.