How to implement the Accumulator interface

644 Views Asked by At

Task: Create class IntegerAccumulator that implements Accumulator that passes the test unit

The code that I've tried below is not working because the test unit only uses 1 parameter when using the add method. The error code that I'm getting is mostly due to the parameters.

I've tried:

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

    }

    T getResult(){
        return null;
    }
}

Here are the provided codes: Main:

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));
    }
}
1

There are 1 best solutions below

1
hc_dev On

Your task(s) as understood from question & comments:

  • implement the given interface Accumulator as IntegerAccumulator
  • make the given test passing

Interface to implement:

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

This interface needs to be implemented by The interface is generic which means it has type-parameter (placeholders D could stand for data as input; T could stand for total as result). Both type-parameters need to be defined by concrete types (like Integer or String) when implemented by a concrete class.

Test to pass (excerpt only):

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
    }

}

Note that this test is not verifying the interface completely. Only one method getResult is tested, the other add(1) differs from the interface. So it must be implemented in order to pass, although not part of the interface.

Solving the test

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;
    }
}

Now your test should go green signaling it has been passed by your implementation. But the main program might still not work correctly (main may not print expected comments), since the interface is not fully implemented yet.

Next steps: to make main work correctly

You might have to:

  • implementing the interface completely
  • and .. what about the accumulator for Strings used in the main method?
  • follow the debendent collaborators: for both we also need to implement the interface DataStore

All of the above implementations couldn't be added as separate classes. Thus loosing the benefit of being independent (loosely coupled). So you can't add and remove as you like. Instead you must edit/change existing code.

You could either modify the main method to implement the interfaces as anonymous class (e.g. directly at their final declaration). Or edit your interface Accumulator directly to implement the method stubs as default implementations.

Using default methods within interfaces is a new feature since Java 8. It can even make your previous implementation obsolete, since you don't have to override to put behavior to the interface methods (it will automatically use the default methods defined).

See this tutorial on default methods