Reputation: 1005
I am new to Java -- coming from the PHP Python world. I am sure this is a simple question and that I'm missing something basic, but after a couple hours of searching and tinkering, I can't figure it out.
I have a Path
class that keeps to points, an In
and an Out
:
public class Path<In extends PointInterface, Out extends PointInterface> {
private In in;
private Out out;
public Path(In in, Out out) {
this.in = in;
this.out = out;
}
public In getIn() {
return in;
}
public Out getOut() {
return out;
}
}
I have many implementations of PointInterface
, for now, let's say Queue
and Endpoint
.
I want to be able to instantiate a Path
object with any combination of those two PointInterface
implementations.
That's all pretty easy.
Path path = new Path<>(new Endpoint(), new Queue());
The Problem Is that each of those implementations has its own handler for both In and Out. So, inside that EndpointInHandler
I can be certain that path.getIn()
will return an Endpoint
(which implements PointInterface
).
But, when I try Endpoint in = path.getIn();
inside that method, I get an Incompatible Types
error saying that it required Endpoint
but found PointInterface
.
Endpoint
implements PointInterface
.
I have tried:
InHandlerInterface<Endpoint>
extends
logic, but then I have the same problem with Object
Can anyone help me understand what I'm missing? Much thanks :)
Code Sample
Inside my Main method:
Path path = new Path<>(new Endpoint(), new Queue());
InHandlerInterface handler = path.getIn().getInHandler(); // returns the EndpointInHandler
handler.handle(path);
Path
detailed above.
PointInterface
:
public interface PointInterface {
InHandlerInterface getInHandler();
}
Endpoint
:
public class Endpoint implements PointInterface {
@Override
public InHandlerInterface getInHandler() {
return new EndpointInHandler();
}
public String specificToEndpoint() {
return "Whatever";
}
}
InHandlerInterface
:
public interface InHandlerInterface {
void handle(Path path);
}
EndpointInHandler
:
public class EndpointInHandler implements InHandlerInterface {
@Override
public void handle(Path path) {
Endpoint in = path.getIn(); // This is giving me the Incompatible types error
String whatever = in.specificToEndpoint();
}
}
Upvotes: 0
Views: 578
Reputation: 8363
When you do Path path = new Path<>(new Endpoint(), new Queue())
, you have effectively lost the type of the generics.
You need to write it as Path<EndPoint, Queue> path = new Path<>(new Endpoint(), new Queue())
so that the compiler is aware what the actual types the generics are referring.
Looking again, I realized that you need to put generics everywhere. It may look weird to see generics appearing everywhere, but this is the way to ensure compile-time type safety. Doing this, you would not need any explicit casts.
Path<Endpoint, Queue> path = new Path<>(new Endpoint(), new Queue());
InHandlerInterface<Endpoint> handler = path.getIn().getInHandler(); // returns the EndpointInHandler
handler.handle(path);
PointInterface:
public interface PointInterface<T extends PointInterface> {
InHandlerInterface<T> getInHandler();
}
Endpoint:
public class Endpoint implements PointInterface<Endpoint> {
@Override
public InHandlerInterface<Endpoint> getInHandler() {
return new EndpointInHandler<>();
}
public String specificToEndpoint() {
return "Whatever";
}
}
InHandlerInterface:
public interface InHandlerInterface<T extends PointInterface<T>> {
void handle(Path<T, ?> path);
}
EndpointInHandler:
public class EndpointInHandler implements InHandlerInterface<Endpoint> {
@Override
public void handle(Path<Endpoint, ?> path) {
Endpoint in = path.getIn(); // This is naturally type safe, and compiler won't complain
String whatever = in.specificToEndpoint();
}
}
Upvotes: 2