Java - 从摘要 class 的 child 调用方法
Java - Calling method from child of abstract class
给定以下摘要class:
public abstract class BaseVersionResponse<T extends BaseVO> {
public abstract void populate(T versionVO);
}
和以下 child class:
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(...)
中。我收到一条看起来像这样的消息:
The method populate(capture#3-of ?) in the type BaseVersionResponse is not applicable for the arguments (BaseVO)
关于上面的 populate
方法。
我的想法是(这显然是不正确的)因为 baseVersionResponse 在代码的这一点上实际上是一个特定的 child 实例,所以 class 会确切知道哪个填充方法从特定的 child class.
调用
我在这里做错了什么?如果这不是正确的方法,还有更好的方法吗?
感谢您的宝贵时间!
如果您只是取出类型捕获(“>”),并且不选中它,它应该可以正常工作。即使使用类型 Object 也会编译。
但是,鉴于您的具体示例,您可能想要的是方法:
public BaseVersionResponse<?> createVersionResponse(String version)
更改为:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version)
然后,而不是使用
BaseVersionResponse<?>
使用
BaseVersionResponse<? extends BaseVO>
因为您知道 return 类型将是实现 interface/class 的那些东西之一。
好的,我今天仔细看了看。问题是通配符虽然是正确的方法,但会阻止您执行以下操作:
BaseVO versionVO = createVersionVO(version);
因为 populate
调用需要 BaseVO 的 扩展 ,而不是不符合条件的实际 BaseVO。这意味着你不能直接传递那个 versionVO 变量。
因此,为了保持类型检查到位,我认为这很好,因为您总是想要一个实现,将几乎所有内容都保留在上面,并更改您的 BaseVersionResponse
class 类似于:
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
。
现在,在您的响应 class 实施中,相应地更改填充方法:
public void populate(BaseVO version) {
VersionVOV1 versionVO = getVersion(version);
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
因此,我们更改了填充方法以采用 BaseVO,getVersion 方法为我们进行转换。所有其他类型检查仍然适用,我们可以开始了。
转换让人感觉不那么干净,但对于您使用的工厂方法,它确实是(我能想到的)保持类型声明和代码模式所做出的保证的唯一方法.
希望对您有所帮助!
给定以下摘要class:
public abstract class BaseVersionResponse<T extends BaseVO> {
public abstract void populate(T versionVO);
}
和以下 child class:
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(...)
中。我收到一条看起来像这样的消息:
The method populate(capture#3-of ?) in the type BaseVersionResponse is not applicable for the arguments (BaseVO)
关于上面的 populate
方法。
我的想法是(这显然是不正确的)因为 baseVersionResponse 在代码的这一点上实际上是一个特定的 child 实例,所以 class 会确切知道哪个填充方法从特定的 child class.
调用我在这里做错了什么?如果这不是正确的方法,还有更好的方法吗?
感谢您的宝贵时间!
如果您只是取出类型捕获(“>”),并且不选中它,它应该可以正常工作。即使使用类型 Object 也会编译。
但是,鉴于您的具体示例,您可能想要的是方法:
public BaseVersionResponse<?> createVersionResponse(String version)
更改为:
public BaseVersionResponse<? extends BaseVO> createVersionResponse(String version)
然后,而不是使用
BaseVersionResponse<?>
使用
BaseVersionResponse<? extends BaseVO>
因为您知道 return 类型将是实现 interface/class 的那些东西之一。
好的,我今天仔细看了看。问题是通配符虽然是正确的方法,但会阻止您执行以下操作:
BaseVO versionVO = createVersionVO(version);
因为 populate
调用需要 BaseVO 的 扩展 ,而不是不符合条件的实际 BaseVO。这意味着你不能直接传递那个 versionVO 变量。
因此,为了保持类型检查到位,我认为这很好,因为您总是想要一个实现,将几乎所有内容都保留在上面,并更改您的 BaseVersionResponse
class 类似于:
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
。
现在,在您的响应 class 实施中,相应地更改填充方法:
public void populate(BaseVO version) {
VersionVOV1 versionVO = getVersion(version);
this.setTestFieldOne(versionVO.getFieldOne());
this.setTestFieldTwo(versionVO.getFieldTwo());
}
因此,我们更改了填充方法以采用 BaseVO,getVersion 方法为我们进行转换。所有其他类型检查仍然适用,我们可以开始了。
转换让人感觉不那么干净,但对于您使用的工厂方法,它确实是(我能想到的)保持类型声明和代码模式所做出的保证的唯一方法.
希望对您有所帮助!