Kotlin父子类出现JVM签名重复的意外重写问题求助
问题场景
在Android Kotlin开发中,自定义Dialog父类BaseDialog和子类DialogPermission出现JVM签名重复的重写冲突,代码及错误信息如下:
子类代码
// 子类 class DialogPermission(myContext : Context) : BaseDialog(myContext) { private var mBtnPermission: Button? = null private var mOnClickListener: DialogInterface.OnClickListener? = null override fun setWidthScale(): Float { return 0.9f } }
父类代码
// 父类 abstract class BaseDialog(protected var context: Context) : Dialog(context, R.style.DialogTransparent) { // 其他实现代码... }
父类错误信息
意外重写:以下声明具有相同的JVM签名(getContext()Landroid/content/Context;):
public final fun `<get-context>`(): Context? defined in com.applock.lock.widget.BaseDialog public final fun getContext(): Context defined in com.applock.lock.widget.BaseDialog
子类错误信息
继承的平台声明冲突:以下声明具有相同的JVM签名(getContext()Landroid/content/Context;):
fun `<get-context>`(): Context? defined in com.applock.lock.widget.DialogPermission fun getContext(): Context defined in com.applock.lock.widget.DialogPermission
问题原因
Android原生Dialog类已自带getContext()方法,而BaseDialog中定义的protected var context: Context属性,Kotlin会自动为其生成名为<get-context>的getter方法,该方法的JVM签名与原生Dialog的getContext()完全一致,从而导致签名冲突。
解决方法
1. 重命名自定义context属性
直接修改父类中的属性名,避免与原生方法签名重叠,例如改为mContext:
abstract class BaseDialog(protected var mContext: Context) : Dialog(mContext, R.style.DialogTransparent) { // 其他实现代码... }
此时Kotlin自动生成的getter为<get-mContext>,不会与原生getContext()产生冲突。
2. 显式覆盖原生getContext()方法
如果不想修改属性名,可显式覆盖原生getContext()方法,返回自定义的context属性值:
abstract class BaseDialog(protected var context: Context) : Dialog(context, R.style.DialogTransparent) { override fun getContext(): Context { return context } // 其他实现代码... }
这种方式会让自定义的context属性与原生方法绑定,消除签名冲突。
3. 为属性getter指定JVM名称
通过@JvmName注解修改Kotlin自动生成的getter的JVM名称,避免与原生方法重名:
abstract class BaseDialog( @get:JvmName("getDialogContext") protected var context: Context ) : Dialog(context, R.style.DialogTransparent) { // 其他实现代码... }
此方法会将属性的getter方法在JVM层面命名为getDialogContext,与原生getContext()签名区分开。
内容的提问来源于stack exchange,提问作者Muhammad Ahmad

