Search code examples
javagenericsconstructorfactory-patternstatic-constructor

Constructor to interface/abstract class using Java generics


Please notice the updates, my question was not clearly formulated. Sorry for that.

Let us assume we have the following code:

class Foo extends/implements AnAbstractClass/AnInterface { /* to make sure the constructor with int as input is implemented */ 
    Foo(int magicInt) { magicInt + 1; /* do some fancy calculations */ }
}

class Bar extends/implements AnAbstractClass/AnInterface { /* to make sure the constructor with int as input is implemented */ 
    Bar(int magicInt) { magicInt + 2; /* do some fancy calculations */ }
}

class Factory<T extends/implements AnAbstractClass/AnInterface> {
    int magicInt = 0; 

    T createNewObject() {
        return new T(magicInt) // obviously, this is not working (*), see below
    }
}

/* how it should work */
Factory<Foo> factory = new Factory<Foo>();
factory.createNewObject() // => Foo with magicInt = 1

Factory<Bar> factory = new Factory<Bar>();
factory.createNewObject() // => Bar with magicInt = 2

At position (*) I don't know what to do. How can I make sure, that the constructor with a signature like this ...(int magicInt) is implemented? I cannot define

  1. a constructor with a certain signature in an interface

    interface AnInterface {
        AnInterface(int magicInt);
    }
    
  2. an abstract class enforcing a certain constructor

    abstract class AnAbstractClass {
        abstract AnAbstractClass(int magicInt);
    }
    

    and this is obviously missing the requirement of an implemented constructor in the subclasses:

    abstract class AnAbstractClass {
       AnAbstractClass(int magicInt) {}
    }
    
  3. a static method within an interface or abstract class, which can be overridden for each implementation of AnInterface or AnAbstractClass (I think of a factory pattern)

What is the way to go?


Solution

  • It sounds like you're really looking for a solution to how to write a generic factory method without a bunch of if/else blocks and without writing one in each class. As such, consider using reflection as in the following code:

    interface Interface {
    }
    
    class Foo implements Interface {
        Foo(int magicInt) { magicInt = magicInt + 1; /* do some fancy calculations */ }
    }
    
    class Bar implements Interface {
        Bar(int magicInt) { magicInt = magicInt + 2; /* do some fancy calculations */ }
    }
    
    class Factory<T extends Interface> {
        int magicInt = 0; 
    
        public T createNewObject(Class<T> typeToMake) {
            try {
                T t = createNewObjectWithReflection(typeToMake);
                return t;
            } catch (Exception e) {
                throw new RuntimeException("Construction failed!", e);
            }
        }
    
        private T createNewObjectWithReflection(Class<T> typeToMake) throws Exception {
            // find the constructor of type to make with a single int argument
            Constructor<T> magicIntConstructor = typeToMake.getDeclaredConstructor(Integer.TYPE);
            // call the constructor with the value of magicInt
            T t = magicIntConstructor.newInstance(magicInt);
            return t;
        }
    }
    
    /* Name of the class has to be "Main" only if the class is public. */
    class Ideone
    {
        public static void main (String[] args) throws java.lang.Exception
        {
            Factory<Foo> fooFactory = new Factory<Foo>();
            Foo foo = fooFactory.createNewObject(Foo.class);
            System.out.println(foo);
    
            Factory<Bar> barFactory = new Factory<Bar>();
            Bar bar = barFactory.createNewObject(Bar.class);
            System.out.println(bar);
        }
    }
    

    You can run the demo at IDEOne here.