Kotlin构造函数属性和调用不同超类构造函数

5

我希望将Kotlin数据类用作异常,这似乎是可行的:

data class MyException(val extraData: Any) : RuntimeException()

我希望在某些情况下能够将一个“cause”传递给超类。不幸的是,数据类只能在其主构造函数中使用“val”/“var”,并且由于默认构造函数调用无参的“RuntimeException()”构造函数,因此似乎我不能这样做而不始终要求传递“cause”,并将其存储为我的类中的字段,这是我不想要的。
我想要的是这样的东西:
data class MyException(val extraData: Any) : RuntimeException() {
    constructor(extraData: Any, cause: Throwable) : this(extraData) super(cause) {}
}

看起来即使我不使用数据类,也无法使用方便的var/val构造函数助手,因为它们只能在主构造函数中使用,必须选择要使用哪个超级构造函数。我能想到的最好方法是这样,这相当冗长:

class MyException : RuntimeException {
    val extraData: Any

    constructor(extraData: Any) {
        this.extraData = extraData
    }

    constructor(extraData: Any, cause: Throwable) : super(cause) {
        this.extraData = extraData
    }
}

我有所遗漏吗?是否真的没有一种方法可以基于重载构造函数有条件地调用不同的父类构造函数,并仍然能够使用 var/ val 参数语法?如果是这样,为什么?是否有更好的方法来完成这种操作?
2个回答

3

由于this(...)super(...)都是构造函数中的第一条语句,因此不能同时调用它们。否则,您将获得编译时错误。

如果任何类包含主构造函数,它们的辅助构造函数必须明确调用其主构造函数,因此在辅助构造函数中根本不能调用额外的super(...)

如果类具有主构造函数,则每个辅助构造函数都需要委托给主构造函数,可以直接或间接地通过另一个辅助构造函数进行。使用this关键字来委托同一类的另一个构造函数。

但是还有一种方法可以通过Throwable#initCause设置原因,例如:

data class MyException(val extraData: Any) : RuntimeException() {
    constructor(extraData: Any, cause: Throwable) : this(extraData) {
        initCause(cause)
    }
}

AND data class 的设计是为了 POJO 而不是 Exception


1
您想要的完全可以使用类似这样的常规类来实现:
class MyException(val extraData: Any, cause: Throwable? = null) : RuntimeException(cause)

在这里,您有一个主构造函数,它始终接受extraData并将其转换为属性。它还接受异常原因,但仅将其传递到超类构造函数中(请注意第二个参数前缺少val)。它还利用了Kotlin中的默认参数,允许您不指定原因。
不幸的是,在您的情况下,您不能特别使用数据类,因为它们的主构造函数不允许具有常规参数。您还必须将原因声明为属性。数据类应该用于最简单的情况,而您有一个更复杂的情况。
如果超类需要有条件地初始化两个不同的构造函数,则您的类中也必须使用两个不同的构造函数。任何构造函数都必须委托超类初始化给另一个构造函数或自己执行。它不能同时执行两者,因为这意味着超类被初始化两次,这没有意义。此外,超类初始化和委托都发生在构造函数本身执行之前,因此您不能有任何关于哪个要执行的逻辑。
您不能有主构造函数,因为存在时它总是需要委托。这意味着属性也必须显式声明,因为属性声明和初始化语法仅适用于主构造函数。

谢谢。这个和@holi-java的答案对于Exception情况都非常好,因为Exception允许空原因并正确处理它。不能调用不同的超级构造函数并且使用var/val参数的更一般性问题仍未得到解答。 - Yona Appletree
@YonaAppletree 简而言之,这是不可能的。但是如果您正在寻找解释,我已经将其添加到答案中了。 - Malcolm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接