为何自定义ArrayAdapter构造方法无需与父类构造方法完全匹配?
我正在跟随教程实现Android ListView的自定义ArrayAdapter,教程中的自定义适配器类如下:
public class NumbersViewAdapter extends ArrayAdapter<NumbersView> { // invoke the suitable constructor of the ArrayAdapter class public NumbersViewAdapter(@NonNull Context context, ArrayList<NumbersView> arrayList) { // pass the context and arrayList for the super // constructor of the ArrayAdapter class super(context, 0, arrayList); } }
我有两个疑问:
- 自定义构造方法
NumbersViewAdapter(@NonNull Context context, ArrayList<NumbersView> arrayList)的参数为何无需与父类调用的super(context, 0, arrayList)参数完全匹配? - 我未找到参数为
(@NonNull Context context, ArrayList<NumbersView> arrayList)的ArrayAdapter构造方法,仅找到类似如下的构造方法:
public ContactListAdapter(@NonNull Context context, int resource, @NonNull ContactInfo[] objects) { super(context, resource, objects); }
目前我尚未进行任何尝试。
1. 自定义构造参数无需与父类调用参数匹配的原因
子类构造方法的参数列表是对外暴露的调用接口,而super()是子类内部调用父类合法构造的逻辑,两者职责完全不同,不需要参数一一对应。
你写的NumbersViewAdapter构造是给外部代码用的(比如在Activity里new NumbersViewAdapter(this, myList)),只需要接收外部调用时必须的参数;而内部的super(context, 0, arrayList)是子类自己适配父类的构造要求——这里的0代表不使用ArrayAdapter默认的布局资源(后续会在getView()里完全自定义布局),把外部传入的两个参数加上这个固定值,凑成父类需要的三个参数,这完全符合Java继承规则:只要子类构造里调用了父类的某个合法构造方法即可,参数可以来自子类构造参数、固定值,甚至子类内部生成的值。
2. 找不到对应参数构造方法的原因
ArrayAdapter本身确实没有(Context, ArrayList<T>)这种参数的构造方法,它的常见合法构造方法包括:
ArrayAdapter(Context context, int resource)ArrayAdapter(Context context, int resource, int textViewResourceId)ArrayAdapter(Context context, int resource, T[] objects)ArrayAdapter(Context context, int resource, List<T> objects)
你看到的ContactListAdapter调用的是(Context, int, T[])的构造,而教程代码里调用的是(Context, int, List<T>)的构造(因为ArrayList实现了List接口),这里的0就是构造方法里的resource参数,所以是合法的。
教程里的自定义构造方法其实是对父类构造的封装,对外简化了调用——外部不需要传入resource参数,子类内部固定传0,让外部代码更简洁。
内容的提问来源于stack exchange,提问作者minh

