2

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

felix
  • 111
  • 1
  • 8
  • 1
    How does one get into a situation like this? This is so confusing to read. – Locke Jan 30 '17 at 22:23
  • From what you did with Foo implementing FooInterface I come to the conclution that there is ONE implementation of FooInterface for all cases. Then why do you insist on binding Foo with Bar through inheritance? Can't Foo just CONTAIN a Bar class? – Eugene Marin Jan 30 '17 at 22:26
  • It feels like there might be some problem with the design of this class hierarchy. Is it not possible to make `bar` extend `FooInterface`? – whaleberg Jan 30 '17 at 22:26
  • Bar can't extend FooInterface as I want to separate the functionality between them (think of Bar and its subclasses as generic data structures, and then FooInterface adds some implementation-specific methods to it). @Gene Marin That's essentially what I am doing now, it can't contain a Bar-instance considering it's an abstract class, but, that `` should be just as possible to write as ``. As I mentioned at end, I have considered simply passing an existing Bar-instance to constructor too. – felix Jan 30 '17 at 22:33
  • How would passing `Bar` instances by a greater hassle than passing a `Class`? I'd say passing `Bar` instances is the best solution so far. I'm also interested in what `A`, `B` and `C` do. If you could eliminate them, you could have just 2 classes, `Bar` and `BarSub extends Bar implements FooInterface` – Jorn Vernee Jan 30 '17 at 22:34
  • Or like @whaleberg said, if every Bar always has a FooInterface "behavior" of itself, Bar should implement FooInterface (which will force A,B,C to implement their behavior). – Eugene Marin Jan 30 '17 at 22:39
  • @whaleberg Edited my post with a clarification of why it's not always feasible to implement FooInterface in Bar – felix Jan 30 '17 at 22:57
  • 2
    In a code comment you ask “why is it customary to spell this [clazz] with z?” Well, you’ll get the answer when you *try* to write it with `s` instead… – Holger Jan 31 '17 at 12:39
  • @Holger heh, while it ought to have been obvious, I somehow forgot to consider java's reserved words xD Thanks for pointing it out :) – felix Jan 31 '17 at 12:46

1 Answers1

3

Instead of passing a Class<T>, you should pass a Supplier<T> to the constructor of Foo. To get an instance, simply call t = supplier.get();. This prevents you from having to deal with reflection issues. To get a supplier you can use either A::new, B::new or C::new. To create an instance of Foo you would call:

new Foo<A>(A::new);

There is no reflection and no exception handling involved.

See also this answer.

Community
  • 1
  • 1
Stefan Dollase
  • 4,530
  • 3
  • 27
  • 51