[英]Java - Calling method from child of abstract class
給定以下抽象類:
public abstract class BaseVersionResponse<T extends BaseVO> {
public abstract void populate(T versionVO);
}
和以下子類:
public class VersionResponseV1 extends BaseVersionResponse<VersionVOV1>
{
protected String testFieldOne;
protected String testFieldTwo;
public String getTestFieldOne() {
return testFieldOne;
}
public void setTestFieldOne(String value) {
this.testFieldOne = value;
}
public String getTestFieldTwo() {
return testFieldTwo;
}
public void setTestFieldTwo(String value) {
this.testFieldTwo = value;
}
@Override
public void populate(VersionVOV1 versionVO) {
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
我希望通過調用方法執行以下操作:
public void getVersionInfo(String version) {
BaseVO versionVO = null;
BaseVersionResponse<? extends BaseVO> baseVersionResponse = null;
baseVersionResponse = createVersionResponse(version);
versionVO = createVersionVO(version);
baseVersionResponse.populate(versionVO);
}
其中createVersionResponse(...)
和createVersionVO(...)
如下所示:
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;
}
和VersionVOV1看起來像這樣:
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)
在上面的populate
方法上。
我的想法是(顯然是不正確的),因為在代碼的這一點上,baseVersionResponse實際上是一個特定的子實例,該類將確切知道要從該特定子類中調用哪個填充方法。
我在這里做錯了什么? 如果這不是正確的方法,還有更好的方法嗎?
感謝您的時間!
如果您只捕獲類型(“ <?>”)的捕獲,並且不選中它,它應該可以正常工作。 即使使用Object類型也可以進行編譯。
但是,給定您的特定示例,您可能想要的是方法:
public BaseVersionResponse<?> createVersionResponse(String version)
變成:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version)
然后,而不是使用
BaseVersionResponse<?>
采用
BaseVersionResponse<? extends BaseVO>
既然您知道返回類型將是實現接口/類的那些事情之一。
好的,我今天對此做了更好的了解。 問題在於,通配符雖然是正確的方法,但卻使您無法執行以下操作:
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);
}
因此,填充方法現在需要一個BaseVO,並且有一個新的getVersion方法可以為我們做一些明確的轉換。 這應該沒問題,因為我們知道工廠將始終提供正確的東西,但是如果另一個調用者不提供,則拋出IllegalArgumentException
。
現在,在您的響應類實現中,相應地更改populate方法:
public void populate(BaseVO version) {
VersionVOV1 versionVO = getVersion(version);
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
因此,我們將populate方法更改為采用BaseVO,而getVersion方法為我們進行了強制轉換。 所有其他類型檢查仍然適用,我們很好。
強制轉換使它感覺不那么干凈,但是對於您正在使用的工廠方法而言,它實際上是使類型聲明和代碼模式保持不變的唯一方法(我能想到)。
希望有幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.