G'day同志。我有一个问题。
除了访问不同的字段外,我有两种完全重复的方法。我无法将字段值作为参数传递,因为访问发生在循环内(简化示例):
public final class Thing {
ImmutableList<Box> boxes;
public int getNumberOfApples() {
int total = 0;
for (Box box : boxes) {
total += box.getApplesCount();
}
return total;
}
public int getNumberOfPears() {
int total = 0;
for (Box box : boxes) {
total += box.getPearsCount();
}
return total;
}
}
我可以将我的水果放入地图并将字段名称作为参数传递,但它看起来很脏,我对当前的课程构成非常满意。所以问题是 - 如何重构我的代码以获得单一的类型方法:
public int getNumberOfFruit(SomethingMagic) {
moreMagic;
return total;
}
Cheerio。
答案 0 :(得分:6)
嗯,你可以有类似的东西:
public interface Function<In, Out> {
Out apply(In input);
}
然后:
public int getCount(Function<Box, Integer> projection) {
int total = 0;
for (Box box : boxes) {
total += projection(box);
}
return total;
}
目前构建该投影的时间很难看,例如
int pears = thing.getCount(new Function<Box, Integer>() {
@Override public Integer apply(Box input) {
return box.getPearsCount();
}
});
但是在Java 8中,使用lambda表达式会更简单:
int pears = thing.getCount(box -> box.getPearsCount());
请注意,通过使界面非通用,Raffaele Rossi的答案比我的更具体。这意味着它可以更高效,因为没有必要包装计数 - 当然,更少可重复使用。您决定使用哪种方法是判断调用,这在很大程度上取决于您的实际用例。
答案 1 :(得分:1)
我建议使用功能性方法。定义一个函数以传递到getNumberOfFruit
,这将检索正确水果的数量。类似的东西:
public interface FruitCounter {
int apply(Box box);
}
public int getNumberOfFruit(FruitCounter counter) {
int total = 0;
for (Box box : boxes) {
total += counter.apply(box);
}
return total;
}
然后通过正确的实现来计算苹果或梨:
int numOfApples theThing.getNumberOfFruit(new FruitCounter() {
@Override
public int apply(Box box) {
return box.getApplesCount();
});
int numOfPears theThing.getNumberOfFruit(new FruitCounter() {
@Override
public int apply(Box box) {
return box.getPearsCount();
});