是否可以根据扩展函数的绑定类型参数来对其进行重载?例如:
abstract class BaseActivity : AppCompatActivity() {
fun <T : Drawable> Int.get(): T?
= ContextCompat.getDrawable(this@BaseActivity, this@get) as T?
fun <T : View> Int.get(): T
= findViewById(this)
}
用法示例:
R.id.webView.get<WebView>() // finds webView
R.drawable.image.get<Drawable>() // gets drawable from resources
(Android代码与该问题无关,这就是我所拥有的)
但这给了我错误:
Conflicting overloads: public fun <T : Drawable> Int.get(): T? defined in xxx.BaseActivity,
public final fun <T : View> Int.get(): T defined in xxx.BaseActivity
不可能吗?
答案 0 :(得分:1)
使用@JvmName
解决平台声明冲突的“正常”方法在这里行不通:Kotlin允许按值参数的类型而不是按类型参数的范围进行重载。
可以通过添加无用的值参数和(与无用的)默认值来解决此问题。
// unchanged
fun <T : Drawable> Int.get(): T? =
ContextCompat.getDrawable(this@BaseActivity, this@get) as T?
// added a parameter
fun <T : View> Int.get(dummy: Nothing? = null): T =
findViewById(this)
一些不相关的注释:
inline
,尤其是那些具有默认参数值的方法findViewById
可以替换为Kotlin Android extensions 答案 1 :(得分:0)
在删除泛型之后,这两个函数将编译为相同的函数签名。
例如,它可能是这样的:
@NotNull
public final String get() {
...
}
编译器无法知道要调用哪个函数。
对此的一种解决方案可以是类型参数化。
interface Some
interface Other
inline fun <reified T> get() = when (T::class) {
Some::class -> "hey"
Other::class -> null
else -> throw UnsupportedOperationException()
}
但是,您必须取消类型限制。
答案 2 :(得分:0)
是否有可能根据扩展函数的绑定类型参数对其进行重载?
一般来说,是的。问题在于参数仅出现在返回类型中,而Java规则(在这方面Kotlin遵循Java的规则)不允许基于其返回类型进行重载,因为返回类型不用于重载解析。这个决定是在泛型出现在Java中之前做出的,因为这样编译器将永远无法选择更具体的方法。此后可以进行修改,但不是。
如果您有一个T
参数,它将起作用。