从抽象类的子类调用Java方法
给定以下抽象类:从抽象类的子类调用Java方法,java,abstract,unbounded-wildcard,Java,Abstract,Unbounded Wildcard,给定以下抽象类: public abstract class BaseVersionResponse<T extends BaseVO> { public abstract void populate(T versionVO); } 版本VOV1如下所示: public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version) { BaseVersionR
public abstract class BaseVersionResponse<T extends BaseVO> {
public abstract void populate(T versionVO);
}
版本VOV1如下所示:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version) {
BaseVersionResponse<? extends BaseVO> specificVersionResponse = null;
if (version.equalsIgnoreCase("V1")) {
specificVersionResponse = new VersionResponseV1();
} else if (version.equalsIgnoreCase("V2"))
specificVersionResponse = new VersionResponseV2();
return specificVersionResponse;
}
public BaseVO createVersionVO(String version) {
BaseVO versionVO = null;
if (version.equalsIgnoreCase("V1")) {
versionVO = new VersionVOV1();
} else if (version.equalsIgnoreCase("V2"))
versionVO = new VersionVOV2();
return versionVO;
}
public class VersionVOV1 extends BaseVO {
private String fieldOne = null;
private String fieldTwo = null;
private String fieldThree = null;
public String getFieldOne() {
return fieldOne;
}
public void setFieldOne(String fieldOne) {
this.fieldOne = fieldOne;
}
public String getFieldTwo() {
return fieldTwo;
}
public void setFieldTwo(String fieldTwo) {
this.fieldTwo = fieldTwo;
}
public String getFieldThree() {
return fieldThree;
}
public void setFieldThree(String fieldThree) {
this.fieldThree = fieldThree;
}
}
当我试图编译这行代码时,我的问题出现了:
baseVersionResponse.populate(versionVO);
在getVersionInfo(…)
中。我收到的信息如下:
BaseVersionResponse类型中的方法populate(capture#3-of?)不适用于参数(BaseVO)
在上面的填充方法中
我的想法是(这显然是错误的),因为baseVersionResponse在代码中的这一点上实际上是一个特定的子实例,所以该类将确切地知道从该特定的子类调用哪个填充方法
我做错了什么?如果这不是正确的方法,有没有更好的方法
谢谢你抽出时间 如果您只是取出类型的捕获(即“”),并将其保留为未选中状态,那么它应该可以正常工作。即使使用类型对象也会编译
但是,根据您的具体示例,您可能需要的是以下方法:
public BaseVersionResponse<?> createVersionResponse(String version)
公共BaseVersionResponse createVersionResponse(字符串版本)
改为:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version)
public-BaseVersionResponse
使用
BaseVersionResponse好的,我今天更仔细地看了一下。问题是,通配符虽然是正确的方式,但却阻止您执行以下操作:
BaseVO versionVO = createVersionVO(version);
因为populate
调用需要BaseVO的扩展,而不是实际的BaseVO,这不符合条件。这意味着您不能直接传递versionVO变量
因此,为了保持类型检查,我认为这是很好的,因为您总是需要一个实现,将几乎所有内容都保留在上面,并将BaseVersionResponse
类更改为类似以下内容:
public abstract class BaseVersionResponse<T extends BaseVO> {
public T getVersion(BaseVO versionVO) {
try {
return (T) versionVO;
} catch (ClassCastException e) {
throw new IllegalArgumentException();
}
}
public abstract void populate(BaseVO versionVO);
}
因此,我们将populate方法改为takebasevo,getVersion方法为我们进行转换。所有其他类型的检查仍然适用,我们可以开始了
强制转换使它感觉不那么干净,但是对于您正在使用的工厂方法来说,它确实是(我能想到的)保持类型声明和代码模式所做保证的唯一方法
希望有帮助 我认为应该在抽象类中更改方法参数。尝试更改populate(T versionVO)的参数类型;方法你能发布版本VOV1吗?@ElliotFrisch当然,我刚刚发布了版本VOV1@prudhvi我有点不确定你的意思。我应该将参数类型更改为什么?如果我将其更改为
,则在这一行上会出现编译错误:baseVersionResponse=createVersionResponse(version)代码>说明:类型不匹配:无法从BaseVersionResponse转换为BaseVersionResponse。这让我更仔细地研究了这个仍然有无限通配符的方法。如果我将这些更改为,那么当然我的工厂将不再工作,并且我得到以下错误类型不匹配:无法在此行上从VersionResponseV1转换为BaseVersionResponse:…=新版本响应v1()代码>。啊,错过了那个细节。我更新了我的答案。这将限制您显式地使用BaseVO的子类,这正是您在这个特定情况下想要的。你现在应该得到同样的结果。嗯,我仍然得到同样的编译错误。不过,我用你的建议更新了上面的原始代码,以便我们看到相同的东西。还有其他想法吗?我觉得我应该能够以某种方式工作……我会想出一个更好的答案。我认为这其中有一个根本性缺陷的症结;我现在真的有工作代码了!非常感谢。我确实觉得它不那么干净,因为它是显式铸造;我其实是想避免这种情况。也许有什么办法,我可以修改我对我的工厂所做的事情,以便它可以被清理?我必须调查一下。再次感谢…这确实解决了我发布的原始问题。很高兴能提供帮助。如果你真的遇到了另一个选择,我很想听听。但正如你所说,我认为你必须大幅修改你的方法,以获得“更干净”的结果。照目前的情况,主要的情况都得到了处理,边缘的情况也得到了适当的处理,代码也不会碍事,所以应该足够了。但这绝对是一个有趣的问题。
BaseVersionResponse<?>
BaseVersionResponse<? extends BaseVO>
BaseVO versionVO = createVersionVO(version);
public abstract class BaseVersionResponse<T extends BaseVO> {
public T getVersion(BaseVO versionVO) {
try {
return (T) versionVO;
} catch (ClassCastException e) {
throw new IllegalArgumentException();
}
}
public abstract void populate(BaseVO versionVO);
}
public void populate(BaseVO version) {
VersionVOV1 versionVO = getVersion(version);
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}