2017-07-14 184 views
2

我想用一個科特林數據類作爲一個例外,它似乎很動聽:科特林構造屬性和調用不同的超構造

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

我還希望能夠在cause傳遞到在那些存在的情況下超級班。不幸的是,數據類只能在它們的主構造函數中有val/var,並且由於默認的構造函數調用無參數構造函數,所以似乎我根本無法做到這一點,因爲沒有總是要求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,使物業出來。它也接受異常原因,但它只將它傳遞給超類構造函數(注意在第二個參數之前不存在val)。它還利用Kotlin中的默認參數,它允許您不指定原因。

不幸的是,你不能在你的情況下專門使用數據類,因爲他們的主要構造函數不允許有常規參數。您也必須將原因聲明爲屬性。數據類應該用於最簡單的情況,而且你有更復雜的情況。

如果超類需要使用兩個不同的構造函數進行有條件的初始化,那麼您將不得不在類中使用兩個不同的構造函數。任何構造函數都必須將超類初始化委託給另一個構造函數,或者自行完成。它不能這樣做,因爲這意味着超類會被初始化兩次,這是沒有意義的。在構造函數本身執行之前,超類的初始化和委託都會發生,所以你不能有任何關於哪一個要做的邏輯。

您不能擁有主構造函數,因爲它總是需要在存在時進行委託。這意味着屬性也必須顯式聲明,因爲屬性聲明和初始化語法僅適用於主構造函數。

+0

謝謝。這個和@ holi-java的答案對於'Exception'情況來說都很好,因爲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是專爲POJO而不是Exception s。