首页 > 解决方案 > 如何实现累加器接口

问题描述

任务:创建实现通过测试单元的累加器的类 IntegerAccumulator

我在下面尝试的代码不起作用,因为测试单元在使用 add 方法时仅使用 1 个参数。我得到的错误代码主要是由于参数。

我试过了:

class IntegerAccumulator implements Accumulator{
    void add(Function function, DataStrore store){

    }

    T getResult(){
        return null;
    }
}

以下是提供的代码: 主要:

public class Main
{
    public static void main(final String[] argv)
    {
        final DataStore<Integer> intStore;
        final DataStore<String> strStore;
        final Accumulator<Integer, Integer> intAccumulator;
        final Accumulator<String, String> strAccumulator;

        intStore = new MemoryDataStore<>(1, 3);
        intStore.setValueAt(0, 0, 10);
        intStore.setValueAt(0, 1, 200);
        intStore.setValueAt(0, 2, 3);

        strStore = new MemoryDataStore<>(1, 3);
        strStore.setValueAt(0, 0, "Hello");
        strStore.setValueAt(0, 1, "Evil");
        strStore.setValueAt(0, 2, "World");

        intAccumulator = new IntegerAccumulator();
        intAccumulator.add((value) -> value, intStore);
        System.out.println(intAccumulator.getResult());

        strAccumulator = new StringAccumulator();
        strAccumulator.add((value) -> value, strStore);
        System.out.println(strAccumulator.getResult()); // Hello, Evil, World

        strStore.setValueAt(0, 0, "Bye");
        strStore.setValueAt(0, 1, null);
        strStore.setValueAt(0, 2, "Bye!"); // Hello, Evil, World, Bye, , Bye!

        strAccumulator.add((value) -> value, strStore);
        System.out.println(strAccumulator.getResult());
    }
}


public interface Accumulator<D, T>
{
    void add(Function<D, T> function, DataStore<D> store);
    T getResult();
}

public interface DataStore<T>
{
    void setValueAt(int row, int col, T value);
    T getValueAt(int row, int col);
    int getRows();
    int getCols();
}
class IntegerAccumulatorTest
{
    @Test
    void add()
    {
        final IntegerAccumulator a;
        final IntegerAccumulator b;

        a = new IntegerAccumulator();
        b = new IntegerAccumulator();
        assertThat(a.getResult(), equalTo(0));
        assertThat(b.getResult(), equalTo(0));

        a.add(1);
        assertThat(a.getResult(), equalTo(1));
        assertThat(b.getResult(), equalTo(0));

        a.add(1);
        assertThat(a.getResult(), equalTo(2));
        assertThat(b.getResult(), equalTo(0));

        a.add(3);
        assertThat(a.getResult(), equalTo(5));
        assertThat(b.getResult(), equalTo(0));

        a.add(null);
        assertThat(a.getResult(), equalTo(5));
        assertThat(b.getResult(), equalTo(0));

        a.add(-6);
        assertThat(a.getResult(), equalTo(-1));
        assertThat(b.getResult(), equalTo(0));
    }
}

标签: javagenericslambdainterfacetestunit

解决方案


从问题和评论中了解您的任务:

  • 将给定的接口实现AccumulatorIntegerAccumulator
  • 使给定的测试通过

实现接口:

public interface Accumulator<D, T>
{
    void add(Function<D, T> function, DataStore<D> store);
    T getResult();
}

该接口需要由该接口是通用的,这意味着它具有类型参数 (占位符D可以代表作为输入的数据T可以代表作为结果的总数)。当由具体类实现时,这两个类型参数都需要由具体类型(如IntegerString)定义。

测试通过(仅摘录):

class IntegerAccumulatorTest
{
    @Test
    void add()
    {
        final IntegerAccumulator a;
        final IntegerAccumulator b;

        a = new IntegerAccumulator();
        b = new IntegerAccumulator();
        assertThat(a.getResult(), equalTo(0));
        assertThat(b.getResult(), equalTo(0));

        a.add(1);
        assertThat(a.getResult(), equalTo(1));
        assertThat(b.getResult(), equalTo(0));

        // further code omitted
    }

}

请注意,此测试并未完全验证接口。只getResult测试了一种方法,另一种add(1)与接口不同。所以它必须实现才能通过,虽然不是接口的一部分。

解决测试

class IntegerAccumulator implements Accumulator<Integer, Integer> {

    // needed to store the result
    private int total = 0;

    void add(Function function, DataStrore store){
      // TODO: needs to be implemented to make `main` work
      // not verified in unit-test
    }

    /**
     * Should return the result as accumulation of previously added data.
     */
    @Override
    Integer getResult(){
        return this.total;
    }

    /**
     * Is verified by the unit-test, although not part of the interface {@link Accumulator}.
     */
    @Override
    public void add(int value) {
      this.total += value;
    }
}

现在你的测试应该是绿色的,表明它已经被你的实现通过了。但是主程序可能仍然无法正常工作(main可能无法打印预期的注释),因为该接口尚未完全实现。

下一步:使main工作正常

您可能必须:

  • 完全实现接口
  • 和.. main 方法中使用的s累加器怎么样?String
  • 跟随 debendent 合作者:对于两者,我们还需要实现接口DataStore

上述所有实现都不能作为单独的类添加。因此失去了独立(松散耦合)的好处。所以你不能随心所欲地添加和删除。相反,您必须编辑/更改现有代码。

您可以修改main方法以将接口实现为匿名类(例如,直接在它们的final声明处)。或直接编辑您interface Accumulator以将方法存根实现为defaultimplementations

在接口中使用default方法是自 Java 8 以来的一项新功能。它甚至可以使您以前的实现过时,因为您不必重写以将行为置于接口方法中(它将自动使用default定义的方法)。

有关默认方法,请参阅本教程


推荐阅读