假设我有一个通用函数:
fun <T: Foo> bar(t: T) { ... }
然后,在某个时间点,我决定用bar(...)
专门作为T
来调用Qux
毫无意义(甚至是错误的),当然, Foo
的一个子类型。但我有充分的理由不改变类层次结构(例如我无法访问该代码)。
有没有办法禁止拨打bar(t)
T
专门用作Qux
的电话?
答案 0 :(得分:3)
有一种方法可以禁止调用某个泛型类型参数:弃用。在这种情况下使用@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
作出反应,因此使用非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?)