2017-07-14 15 views
2

異なるスーパークラスのコンストラクタを呼び出す:Kotlinのコンストラクタのプロパティと、私は罰金思われる、例外として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使用できる方法はありませんか?もしそうなら、なぜですか?このようなことをするより良い方法がありますか?

答えて

1

は、このような通常のクラスと完全になんとかです:ここで

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

あなたは常にextraDataに取り、それのうち、財産を作る主なコンストラクタを持っています。それは例外の原因も取りますが、スーパークラスのコンストラクタに渡します(2番目のパラメータの前にvalがないことに注意してください)。また、Kotlinのデフォルト引数を利用するため、原因を特定できません。

残念ながら、プライマリコンストラクタが正規の引数を持つことが許可されていないため、特にケースではデータクラスを使用することはできません。あなたはその原因をプロパティとして宣言しなければなりません。データクラスは最も簡単な場合に使用されるはずですが、より複雑なものがあります。

スーパークラスを2つの異なるコンストラクタで条件付きで初期化する必要がある場合は、クラス内で2つの異なるコンストラクタも使用する必要があります。どのコンストラクタも、スーパークラスの初期化を別のコンストラクタに委譲するか、それ自体を行う必要があります。これは、スーパークラスが2回初期化されたことを意味するため、両方を行うことはできませんが、それは意味をなさないものです。また、スーパークラスの初期化と委譲の両方がコンストラクタが実行される前に行われるため、どちらを実行するかに関するロジックを持つことはできません。

プライマリコンストラクタを持つことはできません。プライマリコンストラクタは、常に存在する場合に委譲する必要があるためです。つまり、プロパティ宣言と初期化構文はプライマリコンストラクタにのみ適用されるため、プロパティを明示的に宣言する必要があります。

+0

ありがとうございました。これと@ holi-javaの答えは、Exceptionがnullの原因を許可して正しく処理するので、Exceptionの場合にはどちらも優れています。異なるスーパーコンストラクタを呼び出すことができず、 'var' /' val'パラメータも使用できないという、より一般的な問題は未だに解決されていません。 –

+0

@ YonaAppletree要するに、これは不可能です。しかし、あなたが説明を探している場合は、私はそれを答えに加えました。 – Malcolm

2

this(...) & super(...)はコンストラクタの最初のステートメントなので、同時に呼び出すことはできません。そうしないと、コンパイル時エラーが発生します。

IF任意のクラスがprimary constructorが含まれ、そのsecondary constructorsは明示的にその主なコンストラクタを呼び出す必要がありますので、あなたは、すべてのセカンダリコンストラクタに追加super(...)を呼び出すことはできません。

クラスにプライマリコンストラクタがある場合、各セカンダリコンストラクタはプライマリコンストラクタに直接または間接的に別のセカンダリコンストラクタを介して委譲する必要があります。同じクラスの別のコンストラクタへの委任はthisキーワード

を使用して行われます。しかしThrowable#initCauseで原因を設定する別の方法は、例えば、そこにある:

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

data classがために設計されていますExceptionではなくPOJOです。何をしたい

関連する問題