Kotlin子类无法重写Java父类BaseProgressIndicator的createSpec方法及访问spec字段
解决BaseProgressIndicator子类重写createSpec方法的访问权限问题
问题场景
无法继承LinearProgressIndicator,转而用Kotlin编写AdvancedLinearProgressIndicator继承BaseProgressIndicator,但遇到两个问题:
- 无法重写
createSpec()方法,报错提示该方法无法访问父类的同名抽象方法 - 无法访问
BaseProgressIndicator的spec成员字段
报错信息
'public open fun createSpec(context: Context, attrs: AttributeSet): LinearProgressIndicatorSpec defined in AdvancedLinearProgressIndicator' has no access to 'public/package/ abstract fun createSpec(context: Context, attrs: AttributeSet): LinearProgressIndicatorSpec! defined in com.google.android.material.progressindicator.BaseProgressIndicator', so it cannot override it
核心代码片段
BaseProgressIndicator(Java核心代码)
public abstract class BaseProgressIndicator<S extends BaseProgressIndicatorSpec> extends ProgressBar { ... S spec; ... protected BaseProgressIndicator( @NonNull Context context, @Nullable AttributeSet attrs, @AttrRes final int defStyleAttr, @StyleRes final int defStyleRes) { super(wrap(context, attrs, defStyleAttr, DEF_STYLE_RES), attrs, defStyleAttr); ... spec = createSpec(context, attrs); ... } abstract S createSpec(@NonNull Context context, @NonNull AttributeSet attrs); ... }
我的Kotlin子类代码
class AdvancedLinearProgressIndicator( context: Context, attrs: AttributeSet?, @AttrRes defStyleAttr: Int ) : BaseProgressIndicator<LinearProgressIndicatorSpec>( context, attrs, defStyleAttr, com.google.android.material.R.style.Widget_Material3_LinearProgressIndicator ) { override fun createSpec(context: Context, attrs: AttributeSet): LinearProgressIndicatorSpec { return LinearProgressIndicatorSpec(context, attrs) } }
模拟测试代码(可正常运行)
BaseSpec.java
import android.content.Context; public abstract class BaseSpec { protected BaseSpec(Context context) { } abstract void validateSpec(); }
AdvancedSpec.java
public final class AdvancedSpec extends BaseSpec { public AdvancedSpec(Context context) { super(context); validateSpec(); } @Override void validateSpec() { } }
Basic.java
import android.content.Context; import android.widget.ProgressBar; import androidx.annotation.NonNull; public abstract class Basic<S extends BaseSpec> extends ProgressBar { S spec; protected Basic(@NonNull Context context) { super(context); spec = createSpec(context); } abstract S createSpec(@NonNull Context context); }
Advanced.kt
import android.content.Context class Advanced(context: Context) : Basic<AdvancedSpec>(context) { override fun createSpec(context: Context): AdvancedSpec { spec.validateSpec() return AdvancedSpec(context) } }
解决方案
问题根源是父类BaseProgressIndicator的createSpec方法实际为包级私有访问权限(Java中未显式声明public的抽象方法默认是包可见),同时spec字段也是包级私有,而你的Kotlin子类不在同一个包下,因此无法重写方法或访问字段。
可行的解决方式:
- 同包继承(推荐):将
AdvancedLinearProgressIndicator类移动到com.google.android.material.progressindicator包下,这是符合Material组件库封装设计的合规方案。 - 组合替代继承:不直接继承
BaseProgressIndicator,而是通过包装LinearProgressIndicator实例的方式扩展功能,暴露需要的自定义方法。 - 反射访问(不推荐):通过反射强行访问
spec字段,但这种方式会破坏封装性,且可能随库版本更新失效。
内容的提问来源于stack exchange,提问作者Jason Holdsworth
相关产品推荐
相关产品推荐

