我正在写一个类,它将对存储在MyObjects列表中的参数进行耗时的计算。由于我想轻松访问List的一些功能,我决定编写它扩展一个列表类型(另一种方法是将List作为我班级中的一个字段并重写所有方法I&# 39;我要去使用,但它看起来像是一个过度复杂的东西。由于计算非常复杂且耗时,而结果仅取决于存储的参数(没有时间影响,没有隐藏的依赖性等),我决定缓存结果。所以我的代码看起来或多或少是这样的:
public class Calculator extends ArrayList<MyObject> {
private double Result = Double.NaN;
public double getResult() {
if (Double.isNaN(Result)) {
Result = CalculateResult();
}
return Result;
}
}
这样,当第一次调用方法getResult()时,它会计算结果,存储它,然后在后续调用期间重用。
现在,可以使用各种方法修改列表的内容,并且许多修改应该清除缓存。要实现这一点,通常我会写一些类似的东西:
public void add(MyObject newvalue) {
super.add(newvalue);
Result = Double.NaN;
}
然而,它不起作用,因为&#34;超级&#34;指的是通用的ArrayList类,因此编译器会产生类型错误。
我的关键是一个明显的技巧是创建一个临时类,它将实现MyObject的ArrayList并使Calculator扩展这个临时类:
public class MyArrayList extends ArrayList<MyObject> {
}
public class Calculator extends MyArrayList {
}
但它看起来又像是一个过度复杂的东西。难道没有更优雅的方法来实现这一结果吗?或许,是否存在类似于SQL中的触发器的机制,只要对List进行任何修改,就会强制我的类清除缓存?
答案 0 :(得分:3)
方法add
应返回布尔值,因此您需要做的就是
public boolean add(MyObject newvalue) {
boolean retVal = super.add(newvalue);
Result = Double.NaN;
return retVal ;
}
答案 1 :(得分:1)
这是一个很好的例子,说明composition over inheritance何时对代码设计有意义。当你的班级真的需要有一个List
的实例漂浮在周围时,你的课将变得混乱不必要的操作。这也意味着你不依赖ArrayList
实施;例如,如果您的算法需要LinkedList
,那该怎么办?
但是,如果你真的想要解决你的问题......
首先,您收到编译器错误的原因是,就Java而言,您尝试覆盖add
方法,但不要非常有签名权。
正确的签名被指定为boolean add(E)
,但您使用void add(E)
的签名覆盖它。这些类型不匹配,因此您将无法获得成功的覆盖,Java将无法编译该类,如您所见。
接下来,创建更多的类来完成与继承和正确覆盖ArrayList
类相同的事情将不会获得任何东西;如果有的话,它将是更多的过度复制。