· 前言:这次是由于写自动化代码过程中,需要编写的3个接口参数,C的参数包含B,B的参数包含A,原本的方法是分别新建一个类的方法作为入参,但是由于代码冗余,以及类过多,因此想优化一下,于是碰到问题1.
结构大概是:
A--接口入参组装(对应问题1)
B--接口
C--接口实现(对应其他问题)
问题1. 简化3个接口的输入类,原本是分开3个类编写,目前是在一个类当中通过内部类继承的方式写(3个接口的入参 SCreditRequest、 SWithdrawRequest、 SLoanRequest
@Datapublic class base{ @ApiModelProperty(notes = "环境",allowableValues="T1,T2", example = "T2") public String env; @ApiModelProperty(notes = "手机号",example="自动生成") public String phone; public class SCreditRequest extends BaseRequestParameter{ } @Data public class SWithdrawRequest extends SCreditRequest{ @ApiModelProperty(notes = "借款期数",allowableValues="6,12", example = "6") public String loanPeriod; @ApiModelProperty(notes = "借款金额",example = "1000") public String loanAmount; @ApiModelProperty(notes = "是否购买",allowableValues="购买,不购买", example = "购买") public String buyInsurance; } @Data public class SLoanRequest extends SWithdrawRequest{ public SLoanRequest(SCreditRequest sCreditRequest){ this.env=stageCreditRequest.getEnv(); this.phone=stageCreditRequest.getPhone(); } public SLoanRequest(SWithdrawRequest sWithdrawRequest){ this.env=sWithdrawRequest.getEnv(); this.phone=sWithdrawRequest.getPhone(); this.loanPeriod=sWithdrawRequest.getLoanPeriod(); this.loanAmount=sWithdrawRequest.getLoanAmount(); this.buyInsurance=sWithdrawRequest.getBuyInsurance(); } @ApiModelProperty(notes = "放款结果",allowableValues = "成功,失败", example = "成功") private String loanResult; }}复制代码
解决了问题1之后,在接口类调用,具体如下:
@ServiceContract(applicationName = "com.abc.XXX")public interface SService { @ApiOperation(value = "开卡",tags = "产品1") Response sCredit(BaseRequestParameter.SCreditRequest request); //BaseRequestParameter.SCreditRequest是问题1中的内部类复制代码
问题2. 然后在接口实现上碰到具体的父类转子类的问题。
原因是,在实现上,3个接口的前置条件比较相似,但是由于前置条件主要处理入参,而上面3个入参的内部类入参个数不一致,最后一个入参会包含更多参数,因此公共方法入参定义为最多参数的内部类BaseRequestParameter.SLoanRequest ,但由于其他接口使用的内部类传参是父类,因此会存在父类转子类的问题,报ClassCastExcept异常。
2.1 刚开始查找到的方法,是先把父类引用指向子类,然后再把父类变量强转为子类,强转之后,接口实现里面前置参数处理的公共方法就可以用了。
BaseRequestParameter.SCreditRequest inner=new BaseRequestParameter().new SLoanRequest(); //父类引用指向子类对象 BaseRequestParameter.SLoanRequest in=new BaseRequestParameter().new SLoanRequest(); DataU datau=new DataU(); //一个参数值的实体类 if(inner instanceof BaseRequestParameter.SLoanRequest){ //此判断用于判断A类是否可以转换成B类 in=(BaseRequestParameter.SLoanRequest) inner; datau=parms.parms(in); //赋值完,可以顺利调用了 }复制代码
上述方法虽然解决了父类到子类的转换,但是并不完全适用于我的脚本,因为我的接口实现,在一开始入参,就传入了父类,也就是已经没有机会再new一个子类,来把父类引用指向子类了。像这样:
@Overridepublic Response sCredit(BaseRequestParameter.SCreditRequest request) { ******}复制代码
上述写法参考:https://blog.csdn.net/jin970505/article/details/78619849
2.1 于是继续查找方法,另一个帖子的思路是将子类实例赋值给父类变量即可,于是我修改了一下构造函数,以解决问题,如下,在接口入参的类中,写如下的构造函数:
@Datapublic class SLoanRequest extends SWithdrawRequest{ public SLoanRequest(SCreditRequest sCreditRequest){ this.env=sCreditRequest.getEnv(); this.phone=sCreditRequest.getPhone(); } public SLoanRequest(SWithdrawRequest sWithdrawRequest){ this.env=sWithdrawRequest.getEnv(); this.phone=sWithdrawRequest.getPhone(); this.loanPeriod=sWithdrawRequest.getLoanPeriod(); this.loanAmount=sWithdrawRequest.getLoanAmount(); this.buyInsurance=sWithdrawRequest.getBuyInsu(); } //下面的是这个子类独有的属性,其他父类雷同 @ApiModelProperty(notes = "结果",allowableValues = "成功,失败", example = "成功") private String Result;}复制代码
上述写法参考:https://blog.csdn.net/u011630575/article/details/80072241
2.3 然后在同事启发下,发现还有反射的方法,然后从网上找了帖子,关键应该也还是先把父类引用指向子类
上述写法来自:https://blog.csdn.net/u010429286/article/details/78541509