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
a constructor with a certain signature in an interface
interface AnInterface {
AnInterface(int magicInt);
}
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) {}
}
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?
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.