使用方法扩展和继承时名称冲突

时间:2019-02-18 12:00:41

标签: android kotlin kotlin-extension

我有一个扩展名

fun Fragment.showToast(message: String, toastLength: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(context, message, toastLength).show()
}

在项目中,我们正在使用MVP:

interface MyContract {
    interface View {
        fun showToast(message: String)
    }
}

class MyFragment : Fragment(), MyContract.View {
    override fun showToast(message: String) {
        showToast(message)
    }
}

因此,在MyFragment.showToast(message)中,我希望调用扩展功能而不是StackOverflowException

是否可以直接调用扩展功能?像这样:

Fragment.showToast(this, message)

还是我只需要给另一个名字?

3 个答案:

答案 0 :(得分:2)

您可以将MyFragment类转换为Fragment并执行以下操作:

class MyFragment : Fragment(), MyContract.View {
    override fun showToast(message: String) {
        val fragment = this as Fragment
        fragment.showToast(message)
    }
}

这样,您将引用 Fragment

的扩展功能。

答案 1 :(得分:1)

您有两种方法可以用完全相同的名称和参数在Fragment实例上调用。

无法区分您要呼叫的那个人。

我要改一个名字。

例如

fun Fragment.toast(message: String, toastLength: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(context, message, toastLength).show()
}

答案 2 :(得分:1)

在签名冲突的情况下,实例方法优先于扩展功能,因此您遇到的行为是预期的行为。

您可以直接引用 shadowed 扩展函数,并使用别名导入它:假设您有一个名为FragmentExt.kt的软件包中包含扩展方法的文件mypkg

package mypkg

fun Fragment.showToast(message: String, toastLength: Int = Toast.LENGTH_SHORT) {
    Toast.makeText(context, message, toastLength).show()
}

因此,您可以按以下方式调用扩展功能(避免调用实例方法):

import mypkg.showToast as extShowToast
val fragment : Fragment = ...
fragment.extShowToast(message)

此方法在MyFragment子类和任何客户端类中均有效。

在Java代码中,您可以通过按文件名对类名使用静态方法访问Kotlin扩展方法作为静态方法来执行类似的操作:如果扩展功能在FragmentExt.kt中,则Java代码可以使用FragmentExtKt.showToats("Message here")