Danny
Danny

Reputation: 4754

Generic Class Problems!

I have been research this all day and I cannot find a solution. I understand the problem of using subclasses and how the compiler wont know what the class will actually be because of the possibility of setting setting it to something else before calling add. I have look everywhere and I still don't know how to fix this problem. I have an abstract class that is a file wrapper. the file wrapper has an arraylist of sheetwrappers. I want the concrete class of excelfile to be able to add excelsheets to its arraylist but I keep getting this error:

The method add(capture#2-of ? extends SheetWrapper) in the type ArrayList is not applicable for the arguments (ExcelSheet)

Here is the necessary code. Only the parts that are involved in the error are pasted here.ExcelSheet is also an abstract class. Any help would be very very appreciated.Thanks!

public abstract class FileWrapper {

    protected ArrayList<? extends SheetWrapper> sheets;


public class ExcelFile extends FileWrapper {

    this.sheets = new ArrayList<ExcelSheet>();
    for(int i = 0; i < wb.getNumberOfSheets(); i++)
    {
        if(ParserTools.isLegitSheet(wb.getSheetAt(i)))
        {
            this.sheets.add(new ExcelSheet(null)); //ERROR HERE
        }
    } 

Upvotes: 0

Views: 177

Answers (3)

ILMTitan
ILMTitan

Reputation: 11017

A second possibility is to make FileWrapper itself generic:

public abstract class FileWrapper<T extends SheetWrapper> {

    protected ArrayList<T> sheets;


    public class ExcelFile extends FileWrapper<ExcelSheet> {

        this.sheets = new ArrayList<ExcelSheet>();
        for(int i = 0; i < wb.getNumberOfSheets(); i++)
        {
            if(ParserTools.isLegitSheet(wb.getSheetAt(i)))
            {
                    this.sheets.add(new ExcelSheet(null));
            }
        }
    }
}

That way, you can use sheets as a list of ExcelSheet anywhere in ExcelFile.

Upvotes: 0

Brett Kail
Brett Kail

Reputation: 33936

See the GenericsFAQ. You want simply:

protected List<SheetWrapper> sheets;

Note that using the interface type "List" is preferable to the concrete implementation class "ArrayList" for a variable declaration (unless specific methods are needed from that class).

Upvotes: 0

Pavel Minaev
Pavel Minaev

Reputation: 101565

Well, you declared a variable as an "ArrayList of some elements that extend SheetWrapper". This means that you cannot add an instance of ExcelSheet to it, since it could actually be an ArrayList of some other type that extends SheetWrapper.

More precisely speaking, add() is not covariant.

If all your code is actually in the same place, then just fill your list before assigning it:

ArrayList<ExcelSheet> sheets = new ArrayList<ExcelSheet>();
for(int i = 0; i < wb.getNumberOfSheets(); i++)
{
    if(ParserTools.isLegitSheet(wb.getSheetAt(i)))
    {
            sheets.add(new ExcelSheet(null)); //ERROR HERE
    }
}
this.sheets = sheets;

If you need to do it from different parts of code, just lift that local to be another private or protected field (e.g. excelSheets) alongside the inherited sheets, and use that.

Upvotes: 1

Related Questions