Unchecked cast warning with abstract method providing specific return value

397 Views Asked by At

I'm writing selenium tests for an app that has very standard pages that can easily be modeled by a generic structure as the base for the pages, with only a few base types (mostly list pages containing a list of records, and edit pages where one can edit one record). To model this I have these two classes:

public abstract class AbstractListPage<E extends EditPage> extends AbstractSelfOpeningPage implements ListPage {

    // Provides the specific object for the edit page when it's opened
    protected abstract E editPageHook();

    public E getEditPage() {

        return editPageHook();
    }

    public E openEditPage(String key, boolean search) {

        //Do page opening stuff like clicking buttons

        // Return new object for the page that has been opened
        return getEditPage();
    }
}

// Implementation class
public class DossiersListPage extends AbstractListPage<DossierPage> {

    @Override
    protected DossierPage<DossiersListPage> editPageHook() {

        return new DossierPage<>(driver, this);
    }
}

// Usage in test, this shows an unchecked cast warning
DossierPage<DossiersListPage> dossierPage = new DossiersListPage(driver).openPage().openEditPage("3905");

I would like to know if there is a good way to fix this, and what am I missing? I'm not having any issues currently, but the warning all over my test code is making me feel a bit iffy.

The reason for the generics here is so I can model elements on my page that return the page they belong to in a fluent way:

public abstract class AbstractPageElement<P extends Page> implements PageElement<P> {

    @Override
    public P click() throws TimeoutException {
        // Do click
        return page;
    }
}

// DossierPage
public class DossierPage<L extends ListPage> extends AbstractEditPage<L> {

    public OrderDate<DossierPage<L>> orderDate = new OrderDate<>(driver, this);
    public OrderType<DossierPage<L>> orderType = new OrderType<>(driver, this);
    public Status<DossierPage<L>> status = new Status<>(driver, this);
}

// Test
dossierPage.orderDate.click()
           .orderType.click()
           .status.click();
2

There are 2 best solutions below

1
On BEST ANSWER

I could reverse-engineer the problem. The DossierPage must look something like this:

public class DossierPage<E extends AbstractListPage> extends EditPage {
    //...
}

So now we're getting the problem. You can solve it by specifying more type arguments:

public class DossiersListPage extends
    AbstractListPage<DossierPage<DossiersListPage>> { // this is the tricky part

    @Override
    protected DossierPage<DossiersListPage> editPageHook() {
        return new DossierPage<>();
    }
    //...
}
2
On

Just add the following line above the line giving the warning:

@SuppressWarnings("unchecked")