カテゴリー
コンピューター

【Android】【Java】継承専用にしたい Activity は abstract でクラス宣言する

ポイント

  • onCreate、onResume、onPause で必ず同じ処理を行う場合はそれらをスーパークラスにまとめたい。
  • しかし、このスーパークラスはアクティビティとして呼び出さないようにしたい。
  • そこで、クラス宣言を abstract で行う一方で、メソッドでは abstract を付けない通常の宣言を行う。
  • abstract でクラス宣言したアクティビティを起動しようとすると java.lang.InstantiationException と RuntimeException を発生させることができる。

onCreate、onResume、onPause で必ず同じ処理を行う場合とは?

たとえば NFC を使う場合ですの♪NFC の読み込み、書き込みを行うアクティビティでは、

  • onCreate で NfcAdapter#getDefaultAdapter を呼び出す
  • onResume で起動中のアクティビティが優先的に NFC を受け取れるよう設定
  • onPause でアクティビティが優先的に NFC を受け取る設定を解除

を行うようにプログラムいたしました。次の参考書を元にしております。

NFC を扱うアクティビティは 2 〜 3 ございますので、たとえば NfcBaseActivity と名づけて onCreate、onResume、onPause の処理を書き、NFC を扱うアクティビティは NfcBaseActivity を継承するようにいたしました。

abstract でクラス宣言したアクティビティを起動すると発生する例外について

試しに、アクティビティのクラス宣言に abstract を付けて、どのようになるか確認いたしました。

結果、次のような実行時例外が発生しました。

05-04 08:04:39.170  11419-11419/com.example.sample E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.nfc, PID: 11419
    java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.example.sample/com.example.sample.MainActivity}: java.lang.InstantiationException: can't instantiate class com.example.sample.MainActivity
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2124)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2248)
            at android.app.ActivityThread.access$800(ActivityThread.java:138)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1199)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5050)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:805)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:621)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.InstantiationException: can't instantiate class com.example.sample.MainActivity
            at java.lang.Class.newInstanceImpl(Native Method)
            at java.lang.Class.newInstance(Class.java:1208)
            at android.app.Instrumentation.newActivity(Instrumentation.java:1061)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2115)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2248)
            at android.app.ActivityThread.access$800(ActivityThread.java:138)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1199)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5050)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:805)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:621)
            at dalvik.system.NativeStart.main(Native Method)

これで、abstact を付けたクラスは継承専用のクラスであることを説明なしに表現できることを確認できました♪

おわりに

クラス宣言に abstract を付けるべきこと、次の本を読むまで思い浮かべることができませんでしたの><。

abstract 修飾子については、もちろん存じておりました。ですけれども、どういう時に使うとどのように嬉しいのか、理解はできておりませんでしたの><。

次の本の12.3 抽象クラスを読んで、どのようなときに使うのか、理解できました♪

なぜ抽象クラスが存在するのか、どのようなときに使うのかが理解できますので、とてもよい本だと思います。文章のコピペ不可能、印刷可能、ファイルの複製可能、PDF の電子書籍版もございます。

また、次のページも参考になります。

以上です。

コメントを残す