9

I have a genericised class that I wish to subclass as follows:

public class SomeTable<T extends BaseTableEntry>
    extends BaseTable<T>
{

    public SomeTable(int rows, int cols)
    {
        super(rows, cols, SomeTableEntry.class);
        //Does not compile:
        //Cannot find symbol: constructor BaseTable(int, int, java.lang.Class<blah.blah.SomeTableEntry.class>)
    }
}

... where the genericised superclass is:

public class BaseTable<T extends BaseTableEntry>
{

    public BaseTable(int rows, int cols, Class<T> clasz)
    {
        ...
    }
...
}

I understand the compiler error, but cannot seem to find a workaround, other than to include an extra parameter in the SomeTable constructor.

Any suggestions?

Thanks!

bguiz
  • 27,371
  • 47
  • 154
  • 243
  • 1
    does the subclass also need to be generic? Or can it be SomeTable extends BaseTable? – Thilo Jan 25 '10 at 04:03
  • No, `SomeTable` does not need to be genericised, `public class SomeTable extends BaseTable` is fine. – bguiz Jan 25 '10 at 05:07

2 Answers2

10

This compiles:

public class SomeTable extends BaseTable<SomeTableEntry> {
    public SomeTable(int rows, int cols)
    {
        super(rows, cols, SomeTableEntry.class);
    }
}

It works with a cast:

public class SomeTable<T extends BaseTableEntry> extends BaseTable<T> {
    public SomeTable(int rows, int cols)
    {
        super(rows, cols, (Class<T>)SomeTableEntry.class);
    }
}

but I'm looking forward to someone posting the explanation for why the compiler requires the cast for the class.

Steve B.
  • 55,454
  • 12
  • 93
  • 132
  • +1. If he really needs SomeTable to be generic as well, I think he will have to duplicate the superclass constructor with the extra Class parameter. – Thilo Jan 25 '10 at 04:13
  • @SteveB.: Just to make sure that the programmer knows what he/she is doing. `super(rows, cols, (Class)Object.class)` will also work, but by doing a cast you are taking the responsibility`. – Adeel Ansari Jan 25 '10 at 04:20
  • Okay, here is a stab at explanation. Since SomeTable is generic, he could declare another subclass `SubTable extends SomeTable`. In this case, the hard-coded SomeTableEntry would not work anymore, because the expected erased type would now be SpecialEntry. So in conclusion, he must either make SubTable non-generic, or propagate the extra class parameter to the next generation. – Thilo Jan 25 '10 at 04:28
  • 1
    Actually, no need for another subclass at all. He can just write `SomeTable x = new SomeTable(row,col)` and be in trouble. – Thilo Jan 25 '10 at 04:36
  • I might throw something into the mix here: I found that if I changed my `BaseTable` constructor to `public BaseTable(int rows, int cols, Class extends T> clasz)` it works as well... – bguiz Jan 25 '10 at 05:11
4

It is possible to define the SomeTable constructor generically if you pass Class to it the same way as you do with the base class:

public class BaseTable<T extends BaseTableEntry>
{
    public BaseTable(int rows, int cols, Class<? extends T> clazz)
    {
        // ...
    }
}

class SomeTable<T extends BaseTableEntry>
extends BaseTable<T>
{
    public SomeTable(int rows, int cols, Class<? extends T> clazz)
    {
        super(rows, cols, clazz);
    }
}
finnw
  • 47,861
  • 24
  • 143
  • 221