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() が呼び出され、リスナーには通知されません。これはオーバーライドが原因です。私が間違っている?