繁体   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