2454


最近になりましてjavaの勉強を始めました。 下記のように抽象クラスでもインスタンスを作成できることを 知ったのですが、ここでわからないことがあります。

[code]

    abstract class mylog{
        public void logout(int i){
            String messageText = "log-" + String.valueOf(i);
            Log.v("my-app",messageText);
        }
    }
    
    public class hoge{
        mylog mylogclass = new mylog(){};
    }
    
[/code]

  1. 調べてみましたところこれは抽象クラスのmylogのインスタンスを 作成しているのではなく、自動でこれを継承したクラスが作成される との記述をどこかの掲示板で見たのですが、この認識で良いのでしょうか？

  2. 抽象クラスのインスタンスを作成できるということに違和感を覚えます。 このようなことが出来ることによって、どのようなメリットがあるので しょうか。

どなたかお分かりになる方、教えていただけますようお願いします。


CC BY-SA 3.0
2014-12-24T01:07:56.827
2447
2014-12-24T16:26:27.240
2014-12-24T01:38:48.350
208
4935
question
android java
抽象クラスのインスタンスを作成できる理由


> 抽象クラスのmylogのインスタンスを作成しているのではなく、自動でこれを継承したクラスが作成される

そのとおりです。クラスファイルを見ると hoge$1.class みたいなものが生成されているハズです。

> 抽象クラスのインスタンスを作成できる～ことによって、どのようなメリットがあるのでしょうか。

ひとことで言えばファイルが少なくなって見通しが良くなります。

Android であれば
[View.OnClickListener](http://developer.android.com/reference/android/view/View.OnClickListener.html)
のようなイベントハンドラを実装する際に、いちいち新しくクラスを作る必要がなくなります。 これはたとえば Activity
にボタンを配置して、それが押された際の動作を記述する際に、 Activity 自身のクラスファイルにその処理を記述できれば、
別のファイルに記述するよりも自然に見えるケースが多い、といったメリットに繋がります。


CC BY-SA 3.0
2014-12-24T01:37:29.873
2453
2014-12-24T01:37:29.873
208
2447
answer


>
> １）調べてみましたところこれは抽象クラスのmylogのインスタンスを作成しているのではなく、自動でこれを継承したクラスが作成されるとの記述をどこかの掲示板で見たのですが、この認識で良いのでしょうか？

その認識で大丈夫です。

> ２）抽象クラスのインスタンスを作成できるということに違和感を覚えます。このようなことが出来ることによって、どのようなメリットがあるのでしょうか。

下のコードような書き方でメソッドをオーバーライドしたり、また、実装したりできるので、いちいちサブクラスを書くよりも短く記述できるのケースがあることが、メリットとしてあるかと思います。

[code]

    public class hoge{
        mylog mylogclass = new mylog(){
            @Override
            public void logout(int i){
                String messageText = "log-overrided-" + String.valueOf(i);
                Log.v("my-app-overrided", messageText);
            }
        };
    }
    
[/code]


CC BY-SA 3.0
2014-12-24T01:42:05.983
2454
2014-12-24T01:42:05.983
2432
2447
answer


> 抽象クラスのインスタンスを作成できる～ことによって、どのようなメリットがあるのでしょうか。

ここだけ補足します。

暗黙的に外側のインスタンスを握るので、外側インスタンスのフィールドやメソッドにアクセスできます。なので、注意しないとActivityインスタンスを握ってしまい、メモリリークの原因になるので注意。

[code]

    public class MyActivity extends Activity {
        private String mToken; // アクセストークン。これはMyActiviyのフィールド
        void myMethod() {
            mylog mylogclass = new mylog(){
                @Override
                public void logout(int i){
                    // mTokenはアクセス可能
                    String messageText = mToken + "log-overrided-" + String.valueOf(i);
                    Log.v("my-app-overrided", messageText);
                }
            };
        }
    }
    
[/code]


CC BY-SA 3.0
2014-12-24T02:29:07.753
2458
2014-12-24T02:29:07.753
845
2447
answer


1 の認識でよいのですが、この様なものは仕様上の名称を知ることも重要です。

この様な名前のないクラスのことを、仕様上 `Anonymous Class`、日本語では`匿名クラス`と呼びます。  
(文脈により`無名クラス`とも言われるかもしれません)

尚、関連する仕様としては、クラス内部で保持するクラスのことを `Inner Class` (`内部クラス`)、クラス内部から見た外のクラスのインスタンスを
`Enclosing Instance` (`エンクロージングインスタンス`) と呼びます。

より詳細な仕様について知りたければ、上記の名称で仕様書等を参照するとよいと思います。


CC BY-SA 3.0
2014-12-24T16:20:16.957
2508
2014-12-24T16:20:16.957
5644
2447
answer


世間一般では、このような方法で生成するのを「匿名クラス」と呼ばれています。
匿名クラスを使うメリットの一つとして、少しレベルが高いですが、ジェネリックスを残したまま使えるというものがあります。 詳細は、次を参照してください。

  * [ジェネリック型引数を実行時型情報に残す方法がある](http://qiita.com/yuba/items/6ad1c0e9d5de196c9e2f#comment-723cd7c9e8b0a00bb8ab)


CC BY-SA 3.0
2014-12-24T16:26:27.240
2509
2014-12-24T16:26:27.240
4278
2447
answer