Иван Петров
Иван Петров

Reputation: 53

Java Generic method with super keyword

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

Answers (3)

akhil_mittal
akhil_mittal

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

Luan Nico
Luan Nico

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 FourDs.

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

Jesper
Jesper

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

Related Questions