扩展扩展另一个抽象 class 的抽象 class 时的构造函数问题
Constructor issue when extending an abstract class that extends another abstract class
无论出于何种原因,我在扩展抽象 class 时遇到问题,扩展了基础抽象 class,实现如下:
ContractBuilder.groovy
:
package com.xxx.builders
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import com.xxx.enums.Frequency
import com.xxx.enums.Signatory
import com.xxx.models.contract.ContractModel
import com.xxx.models.contract.details.BankDetailModel
import com.xxx.utils.SMDDateUtils
public class ContractBuilder extends BaseFinderBuilder<ContractModel> {
public ContractBuilder() {
super(findTestData('PracticeContractData'))
}
@Override
public ContractModel createModelFromRow(List<Object> row) {
return new ContractModel(
Integer.parseInt(row[0]),
SMDDateUtils.toDate(row[2]),
SMDDateUtils.toDate(row[3]),
Integer.parseInt(row[4]),
row[6],
Double.parseDouble(row[5]),
Frequency.valueOfText(row[7]),
Integer.parseInt(row[8]),
Integer.parseInt(row[10]),
(row[11] == 'Y'),
Integer.parseInt(row[12]),
row[13],
Signatory.valueOfText(row[14]),
this.createBankDetailModel(row),
Double.valueOf(row[18]),
)
}
public BankDetailModel createBankDetailModel(row) {
return new BankDetailModel(Double.valueOf(row[15]), Double.valueOf(row[16]), Double.valueOf(row[17]));
}
}
BaseFinderBuilder.groovy
:
package com.xxx.builders
public abstract class BaseFinderBuilder<T> extends BaseModelBuilder<T>{
protected int primaryKeyIdx = 1;
public T createModelFromID(int id) {
return this.createModelFromRowNum(this.findIndex(id));
}
protected int findIndex(int foreignKey) {
for (int rowIdx = 0; rowIdx < this.testData.getRowNumbers(); rowIdx++) {
if (Integer.parseInt(this.testData.getValue(this.primaryKeyIdx, rowIdx + 1)) == foreignKey) {
return rowIdx
}
}
return -1
}
}
BaseModelBuilder.groovy
:
package com.xxx.builders
import java.util.stream.Collectors
import com.kms.katalon.core.testdata.TestData
public abstract class BaseModelBuilder<T> {
protected TestData testData;
public BaseModelBuilder() {
this.init();
}
public BaseModelBuilder(TestData testData) {
this.testData = testData;
this.init();
}
protected void init() {
// implementation go here
}
public List<T> createModels() {
return this.testData.getAllData()
.stream()
.filter { row ->
row.stream().anyMatch { String cell ->
cell != null && !cell.isEmpty()
}
}
.map { row -> this.createModelFromRow(row) }
.collect(Collectors.toList())
}
public T createModelFromRowNum(int rowNum) {
return this.createModelFromRow(this.testData.getAllData().get(rowNum))
}
public abstract T createModelFromRow(List<Object> row)
}
当我 运行 一个使用 ContractBuilder
的测试用例时,我面临以下问题:
groovy.lang.GroovyRuntimeException: Could not find matching constructor for: com.xxx.builders.BaseFinderBuilder(com.kms.katalon.core.testdata.reader.SheetPOI)
at com.xxx.builders.ContractBuilder.<init>(ContractBuilder.groovy:14)
at com.xxx.builders.PracticeBuilder.init(PracticeBuilder.groovy:26)
at com.xxx.builders.BaseModelBuilder.<init>(BaseModelBuilder.groovy:16)
at com.xxx.builders.PracticeBuilder.<init>(PracticeBuilder.groovy:20)
at New Zoho - 02 Create Practice.run(New Zoho - 02 Create Practice:15)
您认为是什么原因造成的?
看起来在派生抽象 class 上没有显式构造函数是导致此问题的原因。
为什么构造函数不沿继承链一路继承?
这里的问题是这样的:Java还有Groovy没有
构造函数继承 - 它只意味着无参数的
subclasses,如果你没有在子class.
中定义一个c'tor
所以这失败了你看到的错误(简化版本
名称,使它更容易理解):
class SuperSuper {
SuperSuper() {
println "default"
}
SuperSuper(text) {
println "hello, $text"
}
}
class Super extends SuperSuper {}
class Clazz extends Super {
Clazz() {
super("World")
}
}
new Clazz()
// → Caught: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: Super(String)
Super
仅“继承”来自 SuperSuper
的一个 c'tor 没有
争论。因此 Clazz
的 c'tor 中的 super()
将起作用(并打印
default
).
这里的解决方法是让in-between-super-class继承all
来自超级 class 和 @InheritConstructors
:
的构造函数
class SuperSuper {
SuperSuper() {
println "default"
}
SuperSuper(text) {
println "hello, $text"
}
}
@groovy.transform.InheritConstructors // XXX
class Super extends SuperSuper {}
class Clazz extends Super {
Clazz() {
super("World")
}
}
new Clazz()
或者当然要走明确的路线,将 c'tors 写在
Super
你真的想用。
附加信息:
- Default constructors and inheritance in Java
- Java Constructor Inheritance
无论出于何种原因,我在扩展抽象 class 时遇到问题,扩展了基础抽象 class,实现如下:
ContractBuilder.groovy
:
package com.xxx.builders
import static com.kms.katalon.core.testdata.TestDataFactory.findTestData
import com.xxx.enums.Frequency
import com.xxx.enums.Signatory
import com.xxx.models.contract.ContractModel
import com.xxx.models.contract.details.BankDetailModel
import com.xxx.utils.SMDDateUtils
public class ContractBuilder extends BaseFinderBuilder<ContractModel> {
public ContractBuilder() {
super(findTestData('PracticeContractData'))
}
@Override
public ContractModel createModelFromRow(List<Object> row) {
return new ContractModel(
Integer.parseInt(row[0]),
SMDDateUtils.toDate(row[2]),
SMDDateUtils.toDate(row[3]),
Integer.parseInt(row[4]),
row[6],
Double.parseDouble(row[5]),
Frequency.valueOfText(row[7]),
Integer.parseInt(row[8]),
Integer.parseInt(row[10]),
(row[11] == 'Y'),
Integer.parseInt(row[12]),
row[13],
Signatory.valueOfText(row[14]),
this.createBankDetailModel(row),
Double.valueOf(row[18]),
)
}
public BankDetailModel createBankDetailModel(row) {
return new BankDetailModel(Double.valueOf(row[15]), Double.valueOf(row[16]), Double.valueOf(row[17]));
}
}
BaseFinderBuilder.groovy
:
package com.xxx.builders
public abstract class BaseFinderBuilder<T> extends BaseModelBuilder<T>{
protected int primaryKeyIdx = 1;
public T createModelFromID(int id) {
return this.createModelFromRowNum(this.findIndex(id));
}
protected int findIndex(int foreignKey) {
for (int rowIdx = 0; rowIdx < this.testData.getRowNumbers(); rowIdx++) {
if (Integer.parseInt(this.testData.getValue(this.primaryKeyIdx, rowIdx + 1)) == foreignKey) {
return rowIdx
}
}
return -1
}
}
BaseModelBuilder.groovy
:
package com.xxx.builders
import java.util.stream.Collectors
import com.kms.katalon.core.testdata.TestData
public abstract class BaseModelBuilder<T> {
protected TestData testData;
public BaseModelBuilder() {
this.init();
}
public BaseModelBuilder(TestData testData) {
this.testData = testData;
this.init();
}
protected void init() {
// implementation go here
}
public List<T> createModels() {
return this.testData.getAllData()
.stream()
.filter { row ->
row.stream().anyMatch { String cell ->
cell != null && !cell.isEmpty()
}
}
.map { row -> this.createModelFromRow(row) }
.collect(Collectors.toList())
}
public T createModelFromRowNum(int rowNum) {
return this.createModelFromRow(this.testData.getAllData().get(rowNum))
}
public abstract T createModelFromRow(List<Object> row)
}
当我 运行 一个使用 ContractBuilder
的测试用例时,我面临以下问题:
groovy.lang.GroovyRuntimeException: Could not find matching constructor for: com.xxx.builders.BaseFinderBuilder(com.kms.katalon.core.testdata.reader.SheetPOI)
at com.xxx.builders.ContractBuilder.<init>(ContractBuilder.groovy:14)
at com.xxx.builders.PracticeBuilder.init(PracticeBuilder.groovy:26)
at com.xxx.builders.BaseModelBuilder.<init>(BaseModelBuilder.groovy:16)
at com.xxx.builders.PracticeBuilder.<init>(PracticeBuilder.groovy:20)
at New Zoho - 02 Create Practice.run(New Zoho - 02 Create Practice:15)
您认为是什么原因造成的?
看起来在派生抽象 class 上没有显式构造函数是导致此问题的原因。
为什么构造函数不沿继承链一路继承?
这里的问题是这样的:Java还有Groovy没有 构造函数继承 - 它只意味着无参数的 subclasses,如果你没有在子class.
中定义一个c'tor所以这失败了你看到的错误(简化版本 名称,使它更容易理解):
class SuperSuper {
SuperSuper() {
println "default"
}
SuperSuper(text) {
println "hello, $text"
}
}
class Super extends SuperSuper {}
class Clazz extends Super {
Clazz() {
super("World")
}
}
new Clazz()
// → Caught: groovy.lang.GroovyRuntimeException: Could not find matching constructor for: Super(String)
Super
仅“继承”来自 SuperSuper
的一个 c'tor 没有
争论。因此 Clazz
的 c'tor 中的 super()
将起作用(并打印
default
).
这里的解决方法是让in-between-super-class继承all
来自超级 class 和 @InheritConstructors
:
class SuperSuper {
SuperSuper() {
println "default"
}
SuperSuper(text) {
println "hello, $text"
}
}
@groovy.transform.InheritConstructors // XXX
class Super extends SuperSuper {}
class Clazz extends Super {
Clazz() {
super("World")
}
}
new Clazz()
或者当然要走明确的路线,将 c'tors 写在
Super
你真的想用。
附加信息:
- Default constructors and inheritance in Java
- Java Constructor Inheritance