Reputation: 4754
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
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
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
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