在java中,如果不在同一个包中,子类不能覆盖基类的默认或私有方法。基类代码:
//base class
public class TestBase {
protected void test() {
defaultTest();
protectedTest();
privateTest();
}
void defaultTest() {
System.out.println("defaultTest");
}
protected void protectedTest() {
System.out.println("protectedTest");
}
private void privateTest() {
System.out.println("privateTest");
}
}
和子类代码:
public class TestImpl extends TestBase {
protected void test() {
super.test();
localTest();
}
private void localTest() {
System.out.println("Impl:localTest");
}
protected void defaultTest() {
System.out.println("Impl:defaultTest");
}
protected void protectedTest() {
System.out.println("Impl:protectedTest");
}
public void privateTest() {
System.out.println("Impl:privateTest");
}
public static void main(String[] args) {
new TestImpl().test();
}
}
让我们将它们放入不同的包中,输出为:
defaultTest
Impl:protectedTest
privateTest
Impl:localTest
这反映了java中的访问控制机制。我们不能覆盖子类中的 defaultTest() 方法。但是在andorid中,我们可以!在 android.widget.AdapterView 类中,有一个默认方法:
void checkSelectionChanged() {
if ((mSelectedPosition != mOldSelectedPosition) || (mSelectedRowId != mOldSelectedRowId)) {
selectionChanged();
mOldSelectedPosition = mSelectedPosition;
mOldSelectedRowId = mSelectedRowId;
}
}
因此,同一包中的任何子类,例如 Spinner,都可以调用 checkSelectionChanged() 方法。然后调用 OnItemSelectedListener。我们可以添加自己的列表器来监听事件,我们会收到更改通知。但是,如果我们扩展 Spinner,比如 CustomSpinner,并在 CustomSpinner 中定义相同的方法,代码如下:
public class CustomSpinner extends Spinner{
public CustomSpinner(Context context, AttributeSet attrs, int defStyle,
int mode) {
super(context, attrs, defStyle, mode);
}
public CustomSpinner(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomSpinner(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomSpinner(Context context, int mode) {
super(context, mode);
}
public CustomSpinner(Context context) {
super(context);
}
void checkSelectionChanged() {
Log.i("CustomSpinner", "Called!");
}
}
然后奇怪的是 CustomSpinner 中的 checkSelectionChanged() 被调用并且我们的监听器永远不会被通知。这是由覆盖引起的。我错了吗?