提供字段访问器方法作为参数

时间:2014-01-15 10:22:51

标签: java

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。

2 个答案:

答案 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();
    });