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、少なくとも。このようなpackage-privateメソッドがある場合は、それをオーバーライドできますが、クラスが同じパッケージに含まれている場合に限り、そうではありません。同じ名前の無関係なメソッドを宣言しただけです。オーバーライドしていません。

@Overrideこれが、メソッドをオーバーライドする場所で使用する必要がある理由です。実際にオーバーライドしていないことを示すコンパイルエラーが生成されます。

于 2012-12-14T08:44:41.397 に答える