I know that there a couple of threads for this topic but I could not figure out where my problem is. Reading up and down the search results I am more puzzled than ever. I hope I can make my problem clear.
I have a message type hierarchy and I have a generic processor hierarchy for these messages. This I have running so far. Now I want to implement a factory method for the processors and get stuck with the generic approach I have chosen. Please have a look at my example:
abstract class Message
{
abstract int getTest();
}
class MyMessage1 extends Message
{
@Override
int getTest()
{
return 1;
}
}
class MyMessage2 extends Message
{
@Override
int getTest()
{
return 2;
}
}
interface Processor<T extends Message>
{
void initialize(final T p_message);
void doWork();
}
abstract class BaseMessageProcessor<T extends Message> implements Processor<T>
{
private T message;
@Override
public void initialize(T p_message)
{
message = p_message;
}
protected T getMessage()
{
return message;
}
}
class MyMessage1Processor extends BaseMessageProcessor<MyMessage1>
{
@Override
public void doWork()
{
// perfectly valid assignment
MyMessage1 msg = getMessage();
// do something
}
}
class MyMessage2Processor extends BaseMessageProcessor<MyMessage2>
{
@Override
public void doWork()
{
// perfectly valid assignment
MyMessage2 msg = getMessage();
// do something
}
}
So far this is valid and working as expected. But now comes the factory:
class ProcessorFactory
{
<T extends Message> Processor<T> createProcessor(final Class<T> p_msgType)
{
if (p_msgType.equals(MyMessage1.class))
{
// Type mismatch: cannot convert from MyMessage1Processor to Processor<T>
return new MyMessage1Processor();
}
else if (p_msgType.equals(MyMessage2.class))
{
// Type mismatch: cannot convert from MyMessage2Processor to Processor<T>
return new MyMessage2Processor();
}
else
{
throw new Exception("Unsupported message type: " + p_msgType);
}
}
}
Maybe it's a stupid failure I am making here but I can't see it. If someone could give me a hint I would be thankful.
Regards
Sebastian
EDIT: OK my fault. The problem is that I get the compiler errors stated as comments as 'default locale' mentioned (e.g., for the second return statement I get the compile error):
Type mismatch: cannot convert from MyMessage2Processor to Processor
To understand why you are failing, you have to understand how type erasure works:
While you clearly know you are doing things right, the compiler doesn't and, most importantly, can't know it, for design, because the information has been cancelled
Let me try to further explain this concept: because of type erasure, the type T is turned at compile time into a java.lang.Object and there is no compile-time information for the Java compiler that says that
if a.getClass().equals(MyClass.class)
then a.getClass()
will be of type MyClass<MyClass>
Important: please avoid to write this code as much as you can because that would lead to horrible design. If you do not want to die in the hell of bugs and unmaintanable code, do not force type-safe languages to use logical evidence of type safety and not compile type evidence. If you forces the type safety by casts in the compiler, you risk that one day you change the class structure and you forget to change the factory, everything compiles fine but at runtime you get a BOOM.
A factory method is in generally a pattern for hiding from the caller the logic of producing an object and if you end up with such a situation, it probably means that you are not using generics correctly. It is much better to write one more class and having a clean design.
Maybe you can add an additional question on : how to implement this pattern in a type-safe way?