簡體   English   中英

Java-從抽象類的子級中調用方法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM