I have created method like this:
public BaseMenu openMenu(MenuItem menuItem) {
utils.clickOnElement(menuItem);
BaseMenu baseMenu = null;
switch (menuItem) {
case FIRST:
baseMenu = new FirstMenu();
break;
case SECOND:
baseMenu = new SecondMenu();
break;
case THIRD:
baseMenu = new ThirdMenu();
break;
}
return baseMenu;
}
It returns type BaseMenu. How to convert it, so that it would return specific menu types (which are extending BaseMenu), like FirstMenu, SecondMenu, etc.?
I tried something like that:
public <T extends BaseMenu> T openMenu(MenuItem menuItem) {
utils.clickOnElement(menuItem);
T baseMenu = null;
switch (menuItem) {
case FIRST:
baseMenu = (T) new FirstMenu();
break;
case SECOND:
baseMenu = (T) new SecondMenu();
break;
case THIRD:
baseMenu = (T) new ThirdMenu();
break;
}
return baseMenu;
}
but it also returned BaseMenu.
How should code look like to work as I am expecting? Is it possible to do it this way? Is there any other way to achieve it?
CodePudding user response:
It is not possible to convert this function. Returning BaseMenu
was a valid solution which described your use case. It should be the caller's responsibility to cast it to the required type if needed.
The main idea of a generic you let the caller determine the type of the generic so your function can focus on the parts you really cares about. So if I call that function and state that I want that generic to be a class I implemented myself, your function will need to use it.
For example, this code sample would be a valid usage of the generic version.
class Foo extends BaseMenu { /* etc. */ }
Foo foo = openMenu(menuItem);
Alternatively, it may make more sense if you also add methods for firstMenu
, secondMenu
, etc. You should really only be selecting the menu this way if you only need to use functionality all BaseMenu
s implement.
CodePudding user response:
public <T extends BaseMenu> T openMenu(MenuItem menuItem) {
utils.clickOnElement(menuItem);
T baseMenu = null;
switch (menuItem) {
case FIRST:
baseMenu = new FirstMenu();
break;
case SECOND:
baseMenu = new SecondMenu();
break;
case THIRD:
baseMenu = new ThirdMenu();
break;
}
return (T) baseMenu;
}
when you call this method! you must use like this:
FirstMenu fm = openMenu(menuItem);
you should not use :
BaseMenu bm = openMenu(menuItem);
cause your method return value is T, that T type is what you handle that return value, if you use BaseMenu to take that return value, that T will be BaseMenu!!