Reputation: 53
I'm practicing Java now and trying to dive into generics. I want to make this code work:
public class TwoD { // simple class to keep two coordinate points
int x, y;
TwoD(int a, int b) {
x = a;
y = b;
}
}
public class ThreeD extends TwoD { //another simple class to extend TwoD and add one more point
int z;
ThreeD(int a, int b, int c) {
super(a, b);
z = c;
}
}
public class FourD extends ThreeD { //just like previous
int t;
FourD(int a, int b, int c, int d) {
super(a, b, c);
t = d;
}
}
public class Coords<T extends TwoD> { //class to keep arrays of objects of any previous class
T[] coords;
Coords(T[] o) {
coords = o;
}
}
Now I want to make a method which will be using objects of TwoD and ThreeD but not FourD. I've tried that:
static void showXYZsub(Coords<? super FourD> c) {
System.out.println("X Y Z:");
for (int i = 0; i < c.coords.length; i++)
System.out.println(c.coords[i].x + " " + c.coords[i].y +
" " + c.coords[i].z);
System.out.println();
}
but I got an error "z cannot be resolved or is not a field".
As far I know, keyword super
should filter object of any class which extending FourD
, and FourD
itself, but even if I'd change FourD
to ThreeD
or TwoD
, the error will be the same.
I.e. if I use super
only TwoD fields are visible, but in case of extends
everything works fine.
Is Coords
class have problem or what? Please help.
And sorry for engrish.
---edit: calling for showXYZsub
FourD fd[] = {
new FourD(1, 2, 3, 4), new FourD(6, 8, 14, 8), new FourD(22, 9, 4, 9),
new FourD(3, -2, -23, 17) };
Coords<FourD> fdlocs = new Coords<FourD>(fd);
showXYZsub(fdlocs);
Upvotes: 2
Views: 303
Reputation: 24157
When you say Coords<? super FourD>
it means to Java Allow every class which is a super class of FourD and it means TwoD and ThreeD are allowed
. Actualy it means one of the class of this family. Check this question for more.
Now both of these classe have x
and y
parameters so it means whatever allowed class we get we are safe with printing them (x
and y
). But when you include z
it has no presence in class TwoD
so if you pass an object of this the program will fail. So Java takes a defensive approach and does not allow you.
What exactly you want is probably allow ThreeD
and FourD
. Now class FourD
extends ThreeD
so the relation Coords<? extends ThreeD>
should work fine becuase it means Allow ThreeD or any one who extends ThreeD (read FourD)
which is what we want`. S that is the solution in that case.
References: http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html
Upvotes: 0
Reputation: 5917
What you are trying to do is impossible, because how are you going to get point.z
when the argument is a TwoD point?
You said
be using objects of TwoD and ThreeD but not FourD
Why are you restricting FourD
objects?
By inheritance, every FourD
is a ThreeD
. So if something takes ThreeD, it should also be able to handle FourD
s.
Note that it makes sense: if your function takes three dimensional points, it won't be able to handle 2D, because it will lack a dimension, but will take 4Ds with no problem, just ignoring the extra one.
Upvotes: 0
Reputation: 206786
Coords<? super FourD> c
This means: c
is a Coords
where the type argument is some unknown type that is a supertype of FourD
.
The member variable z
was defined in ThreeD
, which is a supertype of FourD
. However, ? super FourD
does not guarantee that the type T
is at least a ThreeD
. It could for example also be TwoD
or Object
, which are also supertypes of FourD
.
So, you cannot access the member variable z
, because the type T
might not have this member variable.
It looks that you actually wanted to use:
Coords<? extends ThreeD> c
Upvotes: 1