Austin
Austin

Reputation: 596

Generic Object Getter

I have the following class structure:

public class BasePage {
    ...
}

public class PageA extends BasePage {
    ...
    public void doStuffA() {}
}

public class PageB extends BasePage {
    ...
    public void doStuffB() {}
}

Then I have another class that contains some getters/setters:

public class TestBase {

private static BasePage currentPage;

public static <T extends BasePage> T getCurrentPage() {
    return (T) currentPage;
}

public static void <T extends BasePage> setBasePage(T page) {
    currentPage = page
}

And inside my tests I'd like use the methods like so:

TestBase.getCurrentPage<PageA>().doStuffA()

But IntelliJ does not seem to like that last syntax. What am I doing wrong?

It says: Cannot resolve symbol 'getCurrentPage'

It does seem to be able to resolve TestBase.getCurrentPage() but I can't access either doStuff methods.

Upvotes: 1

Views: 1189

Answers (2)

Tamas Rev
Tamas Rev

Reputation: 7166

Quick fix

As @Andrew pointed out, this is how you can specify a generic type for a static method:

TestBase.<PageA>getCurrentPage().doStuffA();

This is the very same syntax we use at Collections.emptyList() :

Collections.<String>emptyList();

Redesign

I'm a little concerned that this isn't really what you need. I.e. you can specify a type for the getCurrentPage(), and another for setCurrentPage(). In both of the cases you're <T extends BasePage>. However, this is a method-level type, so you can change them by each invocation. Say for instance, this passes the compiler. On the other hand, it will give you a ClassCastException:

TestBase.<PageB>setBasePage(new PageB());
TestBase.<PageA>getCurrentPage().doStuffA(); // Fine for the compiler. Throws an Exception though

I would rewrite currentPage as a non-static field and I'd use a class-level type for this case:

public class TestBase <T extends BasePage> {

    private T currentPage;

    public T getCurrentPage() {
        return currentPage;
    }

    public void setBasePage(T page) {
        currentPage = page;
    }

}

It makes the syntax easy:

TestBase<PageA> testBase = new TestBase<>(); // specify the page type
testBase.setBasePage(new PageA());
testBase.getCurrentPage().doStuffA(); // easy-peasy

Also, the compiler will spot type errors for you:

TestBase<PageA> testBase = new TestBase<>(); // specify the page type
testBase.setBasePage(new PageB()); // compiler error

Upvotes: 0

wylasr
wylasr

Reputation: 117

(PageA)TestBase.getCurrentPage().doStuffA()

Upvotes: 3

Related Questions