I have a class called Point
, with a method neighbors()
that returns an array of Point
s:
public class Point {
public Point[] neighbors() { /* implementation not shown */ }
}
I have a subclass of Point
, called SpecialPoint
that overrides neighbors()
to return an array of SpecialPoint
s instead of Point
s. I think this is called covariant return types.
public class SpecialPoint extends Point {
public SpecialPoint[] neighbors() { /* implementation not shown */ }
}
In a separate class, I want to make use of Point
and SpecialPoint
with generics
public <P extends Point> P doStuff(P point) {
P[] neighbors = point.neighbors();
// more stuff here including return
}
This will not compile, because the compiler can only guarantee that P
is some subclass of Point
, but there is no guarantee that every subclass of Point
will override neighbors()
to return an array of itself as I happen to have done with SpecialPoint
, so Java only knows that P#neighbors()
returns Point[]
, not P[]
.
How do I guarantee that each subclass overrides neighbors()
with a covariant return type so I can use it with generics?
You may use an interface:
public interface Point<P extends Point<P>> {
P[] neighbors();
}
public class SimplePoint implements Point<SimplePoint> {
@Override
public SimplePoint[] neighbors() { /* ... */ }
}
public class SpecialPoint implements Point<SpecialPoint> {
@Override
public SpecialPoint[] neighbors() { /* ... */ }
}
Then:
public <P extends Point<P>> P doStuff(P point) {
P[] neighbors = point.neighbors();
/* ... */
}
If you still need to factorize code between the implementations, then better use an abstract class:
public abstract class Point<P extends Point<P>> {
public abstract P[] neighbors();
public void commonMethod() { /* ... */ }
}
public class SimplePoint extends Point<SimplePoint> { /* ... */ }
public class SpecialPoint extends Point<SpecialPoint> { /* ... */ }
Possibly an interface Point
solves your problem:
public class Test
{
public interface Point {
public Point[] neighbors();
}
public class SpecialPoint implements Point {
public SpecialPoint[] neighbors() { return null; }
}
public class SpecialPoint2 implements Point {
public SpecialPoint2[] neighbors() { return null; }
}
public Point doStuff(SpecialPoint point) {
Point[] neighbors = point.neighbors();
return neighbors[0];
}
public Point doStuff(SpecialPoint2 point) {
Point[] neighbors = point.neighbors();
return neighbors[0];
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.