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

我想使用kotlin数据类作为例外,这似乎很好:

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

我也希望在存在这样的情况下能够把cause传给超类。 不幸的是,数据类只能在他们的主要构造函数中有val / var ,并且由于默认的构造函数调用了无参数RuntimeException()构造函数,所以似乎我根本无法做到这一点,总是要求传递存储为在我的班级,我不想要的领域。

我想要的是这样的:

 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参数语法? 如果是这样,为什么? 有没有更好的方法来做这种事情?

你想要的是像这样的普通班级完全可行的:

 class MyException(val extraData: Any, cause: Throwable? = null) : RuntimeException(cause) 

在这里你有一个主要的构造函数,它总是接受extraData并使其属性。 它也接受异常的原因,但它只传递给超类的构造函数(注意在第二个参数之前没有val )。 它也利用了Kotlin中的默认参数,它允许你不指定原因。

不幸的是,在你的情况下你不能使用数据类,因为他们的主要构造函数不允许有正则参数。 您也必须将原因声明为属性。 数据类应该用于最简单的情况,而且你有一个更复杂的。

如果超类需要使用两个不同的构造函数进行有条件的初始化,那么在类中也必须使用两个不同的构造函数。 任何构造函数都必须将超类初始化委托给另一个构造函数,或者自己做。 它不能这样做,因为这意味着超类初始化两次,这是没有意义的。 而且,超类的初始化和委托都是在构造函数自身执行之前发生的,所以你不能有任何关于哪个方法的逻辑。

你不能有一个主要的构造函数,因为它总是需要被委托给它。 这意味着属性也必须显式声明,因为属性声明和初始化语法只适用于主构造函数。

既然this(...)super(...)是构造函数中的第一个语句,所以不能同时调用它。 否则,您将获得编译时错误。

如果任何类包含主构造函数 ,则它们的次构造函数必须明确地调用它的主构造函数,所以根本不能在次构造函数上调用额外的super(...)

如果类有主构造函数,则每个次构造函数都需要通过另一个次构造函数直接或间接地委托给主构造函数。 向同一类的另一个构造函数的委托使用this关键字完成

但是还有另一种方法来设置Throwable#initCause的原因,例如:

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

而数据类是为POJO而不是Exception设计的。