I have an Interface (lets call it FooInterface) that I implement in various subclasses (We can call them X, Y, Z) of subclasses (Let's call them A, B, C) of an Abstract class (Let's call it Bar). But it feels wasteful to have to write (copy) the same methods in all of them, even more so considering they are nothing but the subclass they extend + those methods from the interface.
As such, I decided to remove the X, Y, Z layer, and make FooInterface an actual class Foo wrapping Bar-instances. But I can't seem to figure out a good way to do this, my first thought was a generic wrapper class:
public abstract class Bar {/*code*/}
public class A extends Bar {/*code*/}
public class B extends Bar {/*code*/}
public class C extends Bar {/*code*/}
/*
* Removed thanks to using the nifty wrapper Foo now!
* I am so happy I decided to do this,
* can't imagine the horrors I would dream of at night if I had
* an extra redundant class for each subclass of Bar like this!
* public class X extends A implements FooInterface {/*implementing FooInterface*/}
* public class Y extends B implements FooInterface {/*implementing FooInterface*/}
* public class Z extends C implements FooInterface {/*implementing FooInterface*/}
*/
public class Foo<T extends Bar> {
private T t;
public Foo() {t = /*code instantiating T*/}
//code implementing the methods from FooInterface
}
This however won't work, as it seems quite difficult to get an instance of T when using generic types in java.
I considered doing something similar to having T being an enum instead:
public class Foo<T extends BarType> {
public enum BarType { A, B, C; }
private T t;
public Foo() {
switch(T) {
// code instantiating t by using an ugly hard-coded switch-case...
// please don't make me!
}
//code implementing the methods from FooInterface
}
}
But I can't honestly imagine how one would be able to use an enum like this. So at this point I am seriously considering giving up on empty constructors, and doing something along the lines of:
// No longer generic and instead pass type to constructor!
public class Foo {
public enum BarType { A, B, C; }
private T t;
public Foo(Bartype bartype) {
switch(T) {
// code instantiating t by using an ugly hard-coded switch-case...
// please don't make me!
}
//code implementing the methods from FooInterface
}
}
Though to avoid having to do hard-coded switch-statements I am more inclined to this version:
public class Foo<T extends Bar> {
private T t;
// Foo is used as such: 'Foo<T> foo = new Foo<T>(T.class);'
public Foo(Class<T> clazz) throws InstantiationException,
IllegalAccessException {
// why is it customary to spell this with z?
t = clazz.newInstance()
//code implementing the methods from FooInterface
}
}
How do I go about making a wrapper like this properly in java? I have considered other ways too, such as in a generic class passing a factory to constructor or doing that ParameterizedType thingie, or in non-generic simply passing an instance of correct class to constructor directly. But all those seems like a major hassle and quite damn ugly, that I would even prefer hard-coded switch-cases with enums like that...
EDIT: As some people have asked why I don't just make Bar implement FooInterface, it's because Bar is a nice pure datastructure, and FooInterface's role is to make it have some methods that are useful for a more specialized implementation. Example, say Bar etc. are normal lists (so its possible I'm not even the one who implemented them), but then my implementation also has to keep track of which ones are cool:
public abstract class List; // Bar
public class LinkedList extends List; // A
public class ArrayList extends List // B
public interface CoolLists { // FooInterface
boolean isCool();
void setCool(boolean cool);
}
public class CoolLinkedList extends LinkedList implements CoolList; // X
public class CoolArrayList extends ArrayList implements CoolList; // Y
And no, I'm not actually re-implementing lists, and if I wanted to keep track of 'cool lists' I would not store a boolean in them and instead use something like a HashSet storing the 'cool' ones :P