Reidar Sollid's Blog

Just another WordPress.com site

Archive for the ‘Java’ Category

Java 8 and mixin with default methods

with 2 comments

I wanted to check out “mixins” in Java 8 or so called default methods in interfaces. So what is default methods in interfaces in Java. Interfaces in JDK 8 can have full method definitions by using the default keyword. Since I am an Scala fanboy I wanted to test the Stackable Trait Pattern. So here goes. First I created an interface called IntQueue with the default methods get and put. I can not extend an abstract class to an interface, so IntQueue must be an interface or else I can not mix it in.

package com.reidarsollid.eight.mixins;

import java.util.Queue;

public interface IntQueue {
    Queue getQueue();

    default int get() {
        return getQueue().remove();
    }

    default void put(int x) {
        getQueue().add(x);
    }

}

So far so good, so then I want to mix in WithDoubling I want to double what comes inn to the put method. I can not call super on an inherited interface but I can call i through the interface like an inner class calling an outer class.

package com.reidarsollid.eight.mixins;

public interface WithDoubling extends IntQueue {
    default void put(int x) {
        IntQueue.super.put(x * 2);
    }
}

So I wanted to create a BasicIntQueue and mix in the WithDoubling interface. This works as I wanted 🙂

package com.reidarsollid.eight.mixins;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;

public class BasicIntQueue implements IntQueue, WithDoubling {
    private Queue integerQueue = new ConcurrentLinkedDeque<>();

    @Override
    public Queue getQueue() {
        return integerQueue;
    }
}

Then I created a WithFilter interface to check if the numbers are above 0.

package com.reidarsollid.eight.mixins;

public interface WithFiltering extends IntQueue {
    default void put(int x) {
        if (x > 0) IntQueue.super.put(x);
    }
}

Then i mixed in the WithFiltering interface in the BasicIntQueue.

package com.reidarsollid.eight.mixins;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;

public class BasicIntQueue implements IntQueue, WithDoubling, WithFiltering {
    private Queue integerQueue = new ConcurrentLinkedDeque<>();

    @Override
    public Queue getQueue() {
        return integerQueue;
    }
}

Thats when the fun stopped, when compiling this I get this compiler error. java: class com.reidarsollid.eight.mixins.BasicIntQueue inherits unrelated defaults for put(int) from types com.reidarsollid.eight.mixins.WithDoubling and com.reidarsollid.eight.mixins.WithFiltering But then again I can solve this puzzle with decorator pattern So first I create an IntQueue interface.

package com.reidarsollid.eight.decorator;

public interface IntQueue {
    int get();
    void put(int x);
}

Then I created the IntQueueDecorator

package com.reidarsollid.eight.decorator;

public abstract class IntQueueDecorator implements IntQueue {
    protected final IntQueue intQueueDecorator;

    public IntQueueDecorator(IntQueue intQueue) {
        this.intQueueDecorator = intQueue;
    }

    public int get() {
        return intQueueDecorator.get();
    }

    public void put(int element) {
        intQueueDecorator.put(element);
    }
}

And now I can add on as many decorators as I want. The Doubling decorator.

public class Doubling extends IntQueueDecorator {
    public Doubling(IntQueue intQueue) {
        super(intQueue);
    }

    @Override
    public int get() {
        return super.get();
    }

    @Override
    public void put(int element) {
        element = element * 2;
        super.put(element);
    }
}

The Filtering decorator.

package com.reidarsollid.eight.decorator;

public class Filtering extends IntQueueDecorator {
    public Filtering(IntQueue intQueue) {
        super(intQueue);
    }

    @Override
    public int get() {
        return super.get();
    }

    @Override
    public void put(int element) {
        if (element >= 0) {
            super.put(element);
        }
    }
}

The Increment decorator.

package com.reidarsollid.eight.decorator;

public class Increment extends IntQueueDecorator {
    public Increment(IntQueue intQueue) {
        super(intQueue);
    }

    @Override
    public int get() {
        return super.get();
    }

    @Override
    public void put(int element) {
        element += 1;
        super.put(element);
    }
}

And then the test class.

package com.reidarsollid.eight.decorator;

import org.junit.Test;

import java.util.NoSuchElementException;

import static junit.framework.Assert.assertEquals;

public class IntQueueDecoratorTest {
    @Test
    public void testDecorating() throws Exception {
        IntQueue intQueue = new BasicIntQueue();
        intQueue.put(2);
        int actualBasic = intQueue.get();
        int expectedBasic = 2;
        assertEquals(expectedBasic, actualBasic);

        intQueue = new Doubling(intQueue);
        intQueue.put(2);
        int actualWithDoubling = intQueue.get();
        int expectedWithDoubling = 4;
        assertEquals(expectedWithDoubling, actualWithDoubling);

        intQueue = new Increment(intQueue);
        intQueue.put(2);
        int actualWithDoublingAndIncrement = intQueue.get();
        int expectedlWithDoublingAndIncrement = 6;
        assertEquals(expectedlWithDoublingAndIncrement, actualWithDoublingAndIncrement);
    }

    @Test(expected = NoSuchElementException.class)
    public void testDecoratingWithFilter() {
        IntQueue intQueue = new Filtering(new Doubling(new Increment(new BasicIntQueue())));
        intQueue.put(-1);
        int actual = intQueue.get();
    }

}

And we have a green deck. Using decorator pattern adds a little more code, but is easy to use and is readable.

Written by reidarsollid

March 28, 2013 at 12:53 pm

Posted in Java, software