我正在尝试为Java的BigDecimal添加一些便捷方法,并创建一个CustomBigDecimal类。 说我想添加一个方法reciprocal()。 我尝试使用以下继承方式执行此操作:
public class CustomBigDecimal extends BigDecimal
{
.....
.....
public CustomBigDecimal reciprocal()
{
.....
}
}
CustomBigDecimal foo1 = new CustomBigDecimal(1);
CustomBigDecimal foo2 = new CustomBigDecimal(2);
CustomBigDecimal foo2 = foo1.add(foo2); //cannot cast superclass to subclass
这种方法的问题在于我无法将超类强制转换为子类(出于我非常清楚的原因)。并且超类的所有方法都返回一个BigDecimal。 我已经想到了使用如下方法解决这个问题的解决方案:
public class CustomBigDecimal
{
private BigDecimal val;
CustomBigDecimal(BigDecimal val)
{
this.val = val;
}
......
......
public CustomBigDecimal add(CustomBigDecimal augend)
{
return new CustomBigDecimal(val.add(augend.getBigDecimal()));
}
.....
.....
public CustomBigDecimal reciprocal()
{
....
}
}
但是如果我采用第二种方法,我必须编写BigDecimal的每个方法。
有没有更好的方法来解决这个问题?
答案 0 :(得分:4)
如果您实际上没有更改BigDecimal
本身的表示形式,并且只是添加了一些辅助方法,那么您可以使用另一个静态包含辅助方法的类。即
class BigDecimalMethods{
public static BigDecimal reciprocal(BigDecimal bd){
}
//etc
}
答案 1 :(得分:1)
忘记继承。它会强制您处理CustomBigDecimal
和非自定义BigDecimal
。
想象一下,如果你想为toProperCase()
类添加一个方便的String
方法,你会怎么做(这是一个非常常见和频繁的问题)。您将被迫创建StringUtils
类,因为String
类是final
。缺点是,您需要使用StringUtils.toProperCase(someString)
而不是someString.toProperCase()
。
如果String
类不是final
,您可以创建一个子类并在那里添加方法。但是这很糟糕,你仍然无法做someString.toProperCase()
,你需要这样的东西:
if (!(someString instanceof MyStringSubclass)) {
someString = new MyStringSubclass(someString);
}
String somethingElse = ((MyStringSubclass) someString).toProperCase();
而且,那段代码确实太可怕了。在CustomBigDecimal
课程中,您遇到了同样的问题:
if (!(someBigDecimal instanceof CustomBigDecimal)) {
someBigDecimal = new CustomBigDecimal(someBigDecimal);
}
CustomBigDecimal somethingElse = ((CustomBigDecimal) someBigDecimal).reciprocal();
而且,那种代码很糟糕。
在ruby,javascript和其他一些语言中,您可以 mixin 将一些新方法添加到现有类中,而无需更改它。这将是解决问题的正确方法。不幸的是,java不允许这样做。因此,更好的解决方案是utils方法:
public class BigDecimalUtils {
private BigDecimalUtils() {}
public static BigDecimal reciprocal(BigDecimal a) {
...
}
}
utils方法是一种反模式,但由于无法将方法混合到现有的java类中,因此这是最好的方法。使用子类仍然是一个更糟糕的反模式。正确的解决方案是将mixins添加到java语言中,但这当然不是一种选择。
注意:我没有考虑改变JDK rt.jar文件中实际类的选项,也没有考虑使用字节码操作类加载器来模拟它。这对此非常严重。
答案 2 :(得分:0)
你可以这样做:
CustomBigDecimal foo1 = new CustomBigDecimal(1);
CustomBigDecimal foo2 = new CustomBigDecimal(2);
CustomBigDecimal foo3 = new CustomBigDecimal(foo1.add(foo2).intValue());
// Or floatValue()...
答案 3 :(得分:0)
您必须实现一个辅助静态方法或类似的构造函数:
public CustomBigDecimal(BigDecimal bigDecimal) {
super(bigDecimal.toString());
}
CustomBigDecimal foo2 = new CustomBigDecimal(foo1.add(foo2));
答案 4 :(得分:0)
但是如果我采用这种方法,我必须实现每一种方法 BigDecimal的。
我认为你不需要实现所有方法。可能是每个构造函数:
class CustomBigDecimal extends BigDecimal
{
public CustomBigDecimal(BigInteger val) {
super(val);
}
public CustomBigDecimal(int i)
{
super(String.valueOf(i));
}
public CustomBigDecimal(String str)
{
super(str);
}
public CustomBigDecimal(BigDecimal bigDecimal)
{
this(bigDecimal.toString());
}
CustomBigDecimal foo1 = new CustomBigDecimal(1);
CustomBigDecimal foo2 = new CustomBigDecimal(2);
CustomBigDecimal foo3 = new CustomBigDecimal(foo1.add(foo2).toString());
CustomBigDecimal foo4 = new CustomBigDecimal(foo1.add(foo2));
}
答案 5 :(得分:0)
Vandale的答案是最好的解决方案。但是,如果你真的想这样做,只需“覆盖”返回BigDecimal的BigDecimal方法
public CustomBigDecimal abs() {
return new CustomBigDecimal(super.abs());
}
问题在于,所有新的CustomBigDecimal返回方法都不会实际覆盖BigDecimal的版本,并且您需要覆盖每个构造函数(有很多),以及额外的CustomBigDecimal(BigDecimal abs)
你可以看到这是多么混乱,为什么我认为你应该采用Vandale的答案