27257


Java初心者です。

[code]

    import java.util.*;
    
    class ListTest{
      MyClass m1 = new MyClass("hoge");
      MyClass m2 = new MyClass("fuga");
    
      List<MyClass>      list1  = new ArrayList<>(Arrays.asList(m1, m2)); //OK    
      ArrayList<MyClass> list2  = new ArrayList<MyClass>(Arrays.asList(m1, m2)); //OK
      MyArrayList        mylist = new MyArrayList(Arrays.asList(m1, m2)); //NG
    }
    
    class MyArrayList extends ArrayList<MyClass>{
      // MyClassのListに対する処理
    }
    
    class MyClass{
      MyClass(String s){}
    }
    
[/code]

このコードをコンパイルすると、

[code]

    ListTest.java:9: エラー: クラス MyArrayListのコンストラクタ MyArrayListは指定された型に適用できません。
      MyArrayList      mylist = new MyArrayList(Arrays.asList(m1, m2)); //NG
                                ^
      期待値: 引数がありません
      検出値: List<MyClass>
      理由: 実引数リストと仮引数リストの長さが異なります
    エラー1個
    
[/code]

と言われてしまいます。  
`MyArrayList`は`ArrayList<MyClass>`を継承し、コンストラクタのオーバーロードもしていないのですが、なぜ`ArrayList<MyClass>`と同じコンストラクタが使えないのでしょうか。  
インタフェースについて何か初歩的なところで躓いている気はするのですがどこが悪いのかわかりません。

また、とりあえず

[code]

    MyArrayList mylist = new MyArrayList();
    mylist.addAll(Arrays.asList(m1,m2));
    
[/code]

とすることでやりたかったことはできているのですが、そもそもこの`ArrayList`を`extend`するやり方自体が変なやり方なのでしょうか？


CC BY-SA 3.0
2016-07-01T19:54:03.710
27256
2016-07-01T23:03:20.597
17024
question
java
スーパークラスと同じコンストラクタが使えないのはなぜ？


**回答**

>
> `MyArrayList`は`ArrayList<MyClass>`を継承し、コンストラクタのオーバーロードもしていないのですが、なぜ`ArrayList<MyClass>`と同じコンストラクタが使えないのでしょうか。

コンストラクタ、static initializer、instance
initializerはメンバではないので継承されない、ということがJava言語仕様で定められています。

<https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.2>

> Constructors, static initializers, and instance initializers are not members
> and therefore are not inherited.
[code]

    class Foo {
        //constructor
        public Foo() {}
    
        //static initializer
        static {}
    
        public final String str;
    
        //instance initializer
        { str = "foo"; }
    }
    
[/code]

そのため、`ArrayList`のコンストラクタを明示的に呼び出すコンストラクタを`MyArrayList`に定義する必要があります。

[code]

    class MyArrayList extends ArrayList<MyClass> {
        public MyArrayList(Collection<MyClass> myClasses) {
            super(myClasses);
        }
    }
    
[/code]

**余談**

では、なぜコンストラクタを定義してない`MyArrayList`が`new
MyArrayList()`できるのかと言うと、コンストラクタが未定義のclassは、引数なしのデフォルトコンストラクタを持つからです。

<https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.8.9>

> If a class contains no constructor declarations, then a default constructor
> is implicitly declared.

更にそのデフォルトコンストラクタ内では暗黙的に親の引数なしのコンストラクタ`super();`が呼び出されます。

`ArrayList`には複数のコンストラクタが定義されているため、デフォルトコンストラクタはありませんが、引数なしのコンストラクタが明示的に定義されているため、`super();`が実行でき、エラーとなりません。

ArrayList (Java Platform SE 8 ) #コンストラクタの詳細  
<http://docs.oracle.com/javase/jp/8/docs/api/java/util/ArrayList.html#constructor.detail>

> ArrayList.java 161-164行目
[code]

>     /**
>      * Constructs an empty list with an initial capacity of ten.
>      */
>     public ArrayList() {
>         this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
>     }
>  
[/code]

下記のように親クラスがデフォルトコンストラクタも引数なしのコンストラクタも持たない場合、エラーとなります。

[code]

    class Base {
        Base(String str) {}
    }
    
    class Extends extends Base {} // There is no default constractor available in 'Base'
    
[/code]

* * *

> そもそもこのArrayListをextendするやり方自体が変なやり方なのでしょうか？

アプローチとして"is-a"(継承)と"has-a"(包含)の2つがあるかと思います。

  * "is-a" : `ArrayList<MyList>`を継承する
  * "has-a" : `ArrayList<MyList>`をメンバに持つ

Javaに標準で用意されている`ArrayList<>`や`HashMap<>`等のコレクションを継承するべきケースは稀で、継承しなければ実現できない場合を除き、継承するべきではありません。

クラスが必要な状況で`List`のメソッドをそのまま使うだけであれば、`ArrayList<MyClass>`をメンバに持つクラスを定義して使用されるのが良いかと思います。

これであれば`List`のメソッドはすべて使えますし、他の型のリストもメンバとして一緒に持つこともできます。

[code]

    class MyContainer {
        private final List<MyClass> myClassList;
    
        public MyContainer() {
            myClassList = new ArrayList<>();
        }
    
        public MyContainer(Collection<MyClass> collection) {
            myClassList = new ArrayList<>(collection);
        }
    
        public List<MyClass> getMyClassList() {
            return myClassList;
        }
    }
    
[/code]


CC BY-SA 3.0
2016-07-01T21:34:36.270
27257
2016-07-01T23:03:20.597
2016-07-01T23:03:20.597
3068
3068
27256
answer