java - 扩展一个扩展另一个抽象类的抽象类时的构造函数问题

标签 java groovy abstract-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)

您认为是什么原因造成的?

看起来派生抽象类上没有显式构造函数是导致此问题的原因。

构造函数为什么不沿着继承链一路继承?

最佳答案

这里的问题是这样的:Java和Groovy都没有 构造函数继承 - 它仅意味着无参数的继承 子类,如果您没有在子类中定义 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() 将起作用(并打印 默认)。

这里的解决方案是让中间父类(super class)继承全部 使用 @InheritConstructors 来自父类(super class)的构造函数:

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 你确实想使用。

其他信息:

关于java - 扩展一个扩展另一个抽象类的抽象类时的构造函数问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69973041/

相关文章:

java - 碧 Jade 报告 : CONCATENATE function not found

flutter - 抽象类的 super 构造函数中的 undefined_named_pa​​rameter

java - 如何在Spring-MVC方法中绑定(bind)抽象类的子类?

java - 如何在多个 JVM 之间拥有一个通用对象

groovy - 无效的文字/长度代码-如何解决此问题?

bash - sh -c : Unterminated quoted string error in groovy call

c# - 实现一个抽象方法,它本身是通用接口(interface)方法的实现

Java泛型和覆盖

java - 打印 Int 和字符串

java - 从 jar 运行程序时的绝对文件路径?