【问题标题】:How to implement the Accumulator interface如何实现累加器接口
【发布时间】:2020-11-03 20:30:14
【问题描述】:

任务:创建实现通过测试单元的累加器的类 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));
    }
}

【问题讨论】:

  • 所以你的主要工作是intAccumulator.add((value) -&gt; value, intStore);。您是否看到使用 a.add(1); 的非工作单元测试有任何区别(例如传递 int-value 1 而不是像 (value) -&gt; value 这样的 功能;或缺少 数据存储) ? datastore 是累加器从中读取其值以累积到结果的源。
  • 是的,我已经尝试更改 Main 类,但缺少一个参数时会引发错误。
  • 测试、实现IntegerAccumulator 和接口Accumulator 目前不适合。您的任务将哪一个作为修复?你至少需要调整一个才能工作!
  • 给出的是测试和累加器接口。 IntegerAccumulator 是我需要创建以适应 Test 和 Accumulator 的一个。
  • 不清楚。并且您绑定了实现IntegerAccumulator ...您可以将您的代码发布为minimal reproducible example(即使它不起作用)。我相信我们会让它工作的????

标签: java generics lambda interface testunit


【解决方案1】:

从问题和 cmets 中理解的您的任务:

  • 将给定的接口Accumulator实现为IntegerAccumulator
  • 使给定的测试通过

实现接口:

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

这个接口需要实现接口是generic这意味着它有type-parameter(占位符D可以代表data 作为输入;T 可以代表 total 作为结果)。当由 concrete 类实现时,这两个类型参数都需要由具体类型(如 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 可能无法打印预期的 cmets),因为该接口尚未完全实现。

后续步骤:让main 正常工作

您可能必须:

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

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

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

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

default methods上查看本教程

【讨论】:

  • 不确定注释是否正确。如果您手头有 IDE,请您测试一下实现。
猜你喜欢
  • 1970-01-01
  • 2018-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-10
  • 2010-10-10
  • 1970-01-01
相关资源
最近更新 更多