在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()并且永远不会通知我们的监听器。这是由于重写造成的。我错了吗?
答案 0 :(得分:1)
Android和Java中的访问控制完全相同。
Spinner
中没有onSelectionChanged()
方法 - 至少不是public
或protected
。如果有像这样的package-private方法,你可以覆盖它,但前提是你的类在同一个包中,而不是。您已经简单地声明了一个具有相同名称的无关方法;它没有压倒一切。
这就是为什么你应该在你想要覆盖方法的地方使用@Override
。它会产生一个编译错误,告诉你实际上没有覆盖。