コンストラクタとは
コンストラクタとは、newで生み出されたインスタンスに自動で情報(フィールド)を渡してくれるものです。
public class Hero {
String name;
int hp;
}
このHeroクラスをインスタンス化すると、値の入っていないHero(nameがnullでhpが0)が生成されてしまいますが
public class Hero {
String name;
int hp;
//コンストラクタ
Hero(){
this.name = "名前";
this.hp = 100;
}
}
こうすることによって値をフィールドに代入できます。
でもこれだと同じ名前と同じHPのHeroしか作ることができません。
魔法使いHP50とか、妖精HP70とかが作れないのです。
なので、自由にキャラクターを作れるようにするためにこのようにします。
public class Hero {
String name;
int hp;
//コンストラクタ
Hero(String name , int hp){
this.name = name;
this.hp = hp;
}
}
これは何をしているかというと、Hero(String name , int hp)でnameとhpを受け取って、フィールドに代入しているのです。
どこから受け取っているのかというと、mainメソッドから受け取っています。
public static void main(String[] args) {
Hero h = new Hero("勇者" , 100);
}
Heroクラスで引数を2つ受け取るコンストラクタを設定したので、呼び出すときも引数を2つ設定して呼び出します。
これが引数1つだとエラーになります。
結果はこうなります。
ちゃんと値が渡されているか確認しましょう。
public static void main(String[] args) {
Hero h = new Hero("勇者" , 100);
System.out.println("名前は" + h.name + "です。");
System.out.println("HPは" + h.hp + "です。");
}
結果は
名前は勇者です。
HPは100です。
ちゃんと渡すことができました。
でもこれだと、名前だけを渡したい場合エラーになってしまいます。
public class Main {
public static void main(String[] args) {
Hero h = new Hero("勇者");//エラーになる
}
}
こんな時はHeroメソッドにコンストラクタを追加します。
public class Hero {
String name;
int hp;
//コンストラクタ
Hero(String name , int hp){ //ひとつ目のコンストラクタ
this.name = name;
this.hp = hp;
}
Hero(String name){ //ふたつ目のコンストラクタ
this.name = name;
this.hp = 50;
}
}
コンストラクタは、名前が同じでも、引数の数が違えば複数設定できるのです。
これをオーバーロードと言います。
もしmainメソッドでnewして呼び出すとき、引数にnameとhpがあったらひとつ目のコンストラクタが呼び出されます。
引数にnameだけがあったらふたつ目のコンストラクタが呼び出されます。
このままでもエラーにはなりませんが、渡されるフィールドが増えてきたりすると、修正や可読性が悪くなってしまいます。
なので
this()
を使います。
これを使うと、同じメソッドにあるコンストラクタを呼び出すことができます。
public class Hero {
String name;
int hp;
//コンストラクタ
Hero(String name , int hp){ //ひとつ目のコンストラクタ
this.name = name;
this.hp = hp;
}
Hero(String name){ //ふたつ目のコンストラクタ
this(name , 50);
}
}
こうなります。
ふたつ目のコンストラクタの中でひとつ目のコンストラクタを呼び出しているのです。
ひとつ目のコンストラクタは引数が2つあるのでthis()の()の中の引数は2つです。
nameはmainメソッドから渡されたものが入り、hpは渡されないので任意のhpを入れます。ここでは50としています。
これで実行すると
public class Main {
public static void main(String[] args) {
Hero h = new Hero("勇者");
System.out.println("名前は" + h.name + "です。");
System.out.println("HPは" + h.hp + "です。");
}
}
結果
名前は勇者です。
HPは50です。
ちゃんと50が渡されてますね。
this()は結構ややこしいですね。ひとつずつ書いたほうが分かりやすいよ!と思ってる方もいると思いますが、そうすると後からフィールドを変更しなければならなくなった時大変になります。
public class Hero {
String name;
int hp;
//コンストラクタ
Hero(String name , int hp){ //ひとつ目のコンストラクタ
this.name = name;
this.hp = hp;
}
Hero(String name){ //ふたつ目のコンストラクタ
this.name = name;
this.hp = 50;
}
}
こんなふうに書いていて、あとからフィールドを変更しなければならなくなると
public class Hero {
String name1; //ここをname1に変更しなければならない。
int hp;
//コンストラクタ
Hero(String name , int hp){ //ひとつ目のコンストラクタ
this.name = name; //エラーになる。
this.hp = hp;
}
Hero(String name){ //ふたつ目のコンストラクタ
this.name = name; //エラーになる。
this.hp = 50;
}
}
この場合2か所直さないといけなくなります。
コンストラクタが2つならまだいいですが、これが増えてくると作業が大変になります。
なん十か所も直していたら一か所くらいミスが出てもおかしくありません。
自分がつまずいた部分だったのでまとめてみました。
間違いがありましたら指摘をお願いします。
nkojimaさんご指摘ありがとうございます。
記事の一部を削除しました。
確かに読み返してみたら可読性とは違いましたね。
送っていただいた記事も参考にさせていただきます。