1

在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() 被调用并且我们的监听器永远不会被通知。这是由覆盖引起的。我错了吗?

4

1 回答 1

1

访问控制在 Android 和 Java 中完全相同。

没有onSelectionChanged()方法Spinner——没有publicprotected至少没有。如果有这样的包私有方法,您可以覆盖它,但前提是您的类在同一个包中,而事实并非如此。您只是声明了一个具有相同名称的不相关方法;它不是压倒一切的。

这就是为什么你应该使用@Override你打算覆盖方法的地方。它会产生一个编译错误,告诉你你实际上并没有覆盖。

于 2012-12-14T08:44:41.397 回答