假設我有一個泛型函數:如何禁止某個參數類型的某個子類型的函數調用?
fun <T: Foo> bar(t: T) { ... }
然後,後來在某個時間點,我決定,這是沒有意義的(甚至是錯誤的)來調用bar(...)
與T
專門爲Qux
,這是當然的, ,其中一個Foo
的亞型。但是我有很強的理由不改變類的層次結構(例如,我沒有訪問該代碼)。
有沒有辦法禁止撥打bar(t)
與T
專門爲Qux
?
假設我有一個泛型函數:如何禁止某個參數類型的某個子類型的函數調用?
fun <T: Foo> bar(t: T) { ... }
然後,後來在某個時間點,我決定,這是沒有意義的(甚至是錯誤的)來調用bar(...)
與T
專門爲Qux
,這是當然的, ,其中一個Foo
的亞型。但是我有很強的理由不改變類的層次結構(例如,我沒有訪問該代碼)。
有沒有辦法禁止撥打bar(t)
與T
專門爲Qux
?
有一種方法可以禁止某個泛型類型參數的調用:棄用。在這種情況下使用@Deprecated
註釋看起來非常笨拙,但它解決了問題(*)。
您可以用更具體的類型定義bar(...)
過載,並與DeprecationLevel.ERROR
水平棄用過載:
@Deprecated("bar should not be called with Qux", level = DeprecationLevel.ERROR)
fun <T : Qux> bar(t: T) = bar(t as Foo)
之後,當bar(...)
調用了Qux
論證解決,棄用過載將採取優先級,因爲它具有更多的具體類型。因此,調用將產生一個編譯時錯誤:
bar(Qux())
^ Using 'bar(T): Unit' is an error. bar should not be called with Qux
(*),但是注意的是,這隻會爲Qux
靜態類型(用於呼叫分辨率的)工作,並且功能仍然可以稱爲bar(Qux() as Foo)
。相當可觀的是,如果只在運行時知道參數類型,則不能產生編譯時錯誤。
同樣的方法也可以用於生產功能應該以某種方式對null
唯一的反應,錯誤或警告,這樣稱他們有沒有空型是沒有意義的:
fun checkNotNull(x: Any?) = x ?: throw IllegalStateException("Should not be null")
@Deprecated("It is meaningless with a not-null argument.", DeprecationLevel.WARNING)
@JvmName("checkNotNull--notNullArgument")
fun checkNotNull(x: Any) = checkNotNull(x as Any?)