假设您有一个接口和两个实现该接口的类:
public interface IElement {
boolean isDisplayed();
}
public class Button implements IElement {
@Override
public boolean isDisplayed() {
// checks if displayed
return false;
}
public void click() {
// clicks
}
}
public class Textbox implements IElement {
@Override
public boolean isDisplayed() {
// checks if displayed
return false;
}
public void enterText(String text) {
// enters text
}
}
在一个完全独立的类中,我们有一个方法,它想要返回一个Button或一个Textbox,具体取决于提供的参数的值。像这样的东西:
public class WhichElement {
public <T extends IElement> T getElement(String elementName) {
if (elementName.equalsIgnoreCase("button")) {
return new Button();
}
else if (elementName.equalsIgnoreCase("textbox")) {
return new Textbox();
}
}
}
然而,由于返回的对象不是类型T,因此失败。 我试过像这样返回界面:
public IElement getElement(String elementName)
但是我不能做我真正想做的事情,这就是:
WhichElement picker = new WhichElement();
picker.getElement("button").click(); <-- errors here because it's an IElement not a Button :(
我可以将它强制转换为正确的对象,并相信该方法可以返回相同的方法,但是这似乎很危险。我更倾向于确定所需对象的类型并直接返回该对象。 有没有办法做我正在尝试的事情?
答案 0 :(得分:3)
您可以在返回之前将getElement()
的结果转换为T
,这将产生编译器警告。
警告是存在的,因为编译器将在调用站点插入一个强制转换,如果运行时结果不是正确的类型,将从没有的位置抛出ClassCastException
。明显的演员。基本上,如果getElement()
不是通用的,编译器会生成您编写的相同代码,并且只返回IElement
。
不是使用一种工厂方法来生成多种类型,而是为每种类型创建不同的工厂方法。这将为您提供类型安全性,确保实际提供应用程序所需的每个元素,帮助重构,并将getElement("buttton")
等运行时错误更改为编译时错误。
依赖注入是另一种方法:给应用程序一个按钮,而不是找到一个按钮。
答案 1 :(得分:0)
有两种方法。
public Button getButton() {
return new Button();
}
public Textbox getTextbox() {
return new Textbox();
}
在语义和代码方面没有太大区别
picker.getButton() // Strongly typed
picker.getElement("button") // Stringly typed
另外,stringly typed版本更长。