0

给定以下抽象类:

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 实际上是一个特定的子实例,所以该类将确切地知道从该特定子类调用哪个填充方法。

我在这里做错了什么?如果这不是正确的方法,是否有更好的方法来做到这一点?

感谢您的时间!

4

2 回答 2

1

好的,我今天仔细看看这个。问题是通配符虽然是正确的方法,但会阻止您执行以下操作:

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 方法现在需要一个 BaseVO,并且有一个新的 getVersion 方法可以为我们进行一些显式转换。这应该没问题,因为我们知道工厂总是会提供正确的东西,但是如果另一个调用者没有,IllegalArgumentException就会抛出 an 。

现在,在您的响应类实现中,相应地更改填充方法:

public void populate(BaseVO version) {
    VersionVOV1 versionVO = getVersion(version);
    this.setTestFieldOne(versionVO.getFieldOne());
    this.setTestFieldTwo(versionVO.getFieldTwo());
}

因此,我们将 populate 方法更改为采用 BaseVO,而 getVersion 方法为我们进行转换。所有其他类型检查仍然适用,我们可以开始了。

铸造使它感觉不那么干净,但是对于您正在使用的工厂方法,它确实是(我能想到的)保持类型声明和代码模式所做出的保证的唯一方法。

希望有帮助!

于 2015-03-20T16:59:30.413 回答
1

如果您只是取出类型的捕获(“<?>”),并且不选中它,它应该可以正常工作。即使使用类型 Object 也会编译。

但是,鉴于您的具体示例,您可能想要的是方法:

public BaseVersionResponse<?> createVersionResponse(String version)

变成:

public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version)

然后,而不是使用

BaseVersionResponse<?>

利用

BaseVersionResponse<? extends BaseVO>

因为您知道返回类型将是实现接口/类的那些东西之一。

于 2015-03-19T01:15:06.070 回答