- ベストアンサー
回答間違い??
class Foo{ Foo(){ System.out.println("Foo"); } Foo(String str){ System.out.println("Foo " + str); } } class Bar extends Foo{ Bar(String str){ Foo(); ←【ココ】 System.out.println("Bar " + str); } public static void main(String args[]){ Bar obj2 = new Bar("Hello"); } } あるテキストの問題で【ココ】の部分に入れる適切な処理として、super()かFoo()が正解でした・・・ しかしこのようにFoo()としてしまうとコンパイルエラーが出ます。 回答間違えだとは思うのですが、 super()以外の回答としてどのようなものがありますでしょうか? ためしにFoo.Foo()とやってみましたがだめでした・・・。 ちなみに Foo Bar Hello と出るようにします。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
> Barのインスタンスを生成した時点で、一度Foo()を呼んでいるようです。 ↑これが super() なんです。つまり、このsuperというのはFooを指しているわけです。ですから、 > スーパークラスFooのコンストラクタを実行するものとばかり思っていました というのは間違っていませんよ。 お察しのとおり、コンストラクタは「連鎖」します。 実は、どんなクラスでもすべてのコンストラクタは必ずスーパークラスのコンストラクタを呼び出すことになっているのです。 ご質問の例では、Bar()コンストラクタの先頭にsuper()があって、そこでスーパークラスのFoo()が呼ばれているわけです。 ではFoo()はどうなのかというと、Fooのスーパークラスであるjava.lang.Objectのコンストラクタ=Object()が呼ばれているわけです。Foo()にはsuper()とは書いてありませんが、書いていない場合はsuper()が省略されていると判断され、コンパイラが強制的にsuper()を追加します。 ではObject()はどうなのかというと、さすがにもうそれ以上のスーパークラスはありませんから、連鎖はここで終わりです。 Object()コンストラクタは実際には何も行わないので気づきにくいですが、実はFoo()の最初でObject()が呼ばれていたわけです。(あまり意味はありませんが) さて、super()でスーパークラスのコンストラクタに連鎖させる代わりに、this()で自分のクラスの別のコンストラクタに連鎖させることもできます。 例えば、Bar() と Bar(String) の2種類のコンストラクタがあるときに、Bar() の先頭で Bar(String) に連鎖させるといった感じです。 // Fooクラスはそのまま class Bar extends Foo{ Bar() { this("Hello"); System.out.println("(~_~)"); } Bar(String str){ super(); System.out.println("Bar " + str); } public static void main(String args[]){ Bar obj2 = new Bar(); } } これを実際に実行してみると、 1. Foo() で 「Foo」 2. Bar(String) で 「Bar Hello」 3. Bar() で 「(~_~)」 が出力されます。 つまり、Bar() - Bar(String) - Foo() - Object() という風に連鎖しているわけです。 ……で、new Foo(); の件ですが、これは単に(別な)インスタンスを生成するだけですね。 Foo foo = new Foo(); の後半部分だけを抜き出したものといえばわかりやすいでしょうか。 Fooのインスタンスを新しく生成し、コンストラクタも実行されるのですが、変数に代入しないので、結局そのインスタンスはそのまま「あの世行き」です。 「あの世行き」という意味では、mainメソッドの Bar obj2 = new Bar("Hello"); も大して変わらないかも。obj2に代入しても、その後obj2が使われることはないから、代入する意味がないってことです。つまり、 Bar obj2 = new Bar("Hello"); でも new Bar("Hello"); でも結果は同じです。 /* なんだかとってもわかりにくい解答を書いてしまった気がする……。ムツカシイ説明より自分でいろいろ実験してみるほうがわかりやすいかも。 */
その他の回答 (3)
- terra5
- ベストアンサー率34% (574/1662)
ここの説明がわかりやすいと思います。 http://msugai.fc2web.com/java/overrideConstructor.html super()を呼ばないと自動的にsuper()が呼ばれるだけです。 実際は、引数つきでコンストラクタを実行したい時に super(1); の様に使うわけです。 >で、new Foo();とするとコンストラクタがさらにもう一回呼ばれ これは、別なFooクラスのオブジェクトが生成されるためです。 Barを生成するために呼ばれるFooのコンストラクタではありません。 >スーパークラスFooのコンストラクタを実行するものとばかり思っていました・・・ その通りのはずです。 >Staticのxと言う変数を定義いたしまして、プログラムのいろんな個所でインクリメントし動作を確かめたところ、 確認方法に問題があるように思います。 実際に使ったコードが明示されてないと正確な判断できませんが。
お礼
>super()を呼ばないと自動的にsuper()が呼ばれるだけです。 ありがとうございます! これですっきりいたしました!
- UKY
- ベストアンサー率50% (604/1207)
コンストラクタの中から別なコンストラクタを呼び出す場合、使えるのは super(); と this(); だけですよ。 確かに、スーパークラスのコンストラクタを呼び出す以上 実質的には Foo(); なのですが、super(); と書かないとエラーになってしまいます。 というわけで、super(); 以外に正解はないです。
お礼
いつもありがとうございます。 このテキストには一応解説があるのですが、 Foo()が正解になっているわりに、 それが正解である理由はまったくかかれておらず、 (もちろん不正解の理由も・・・) 戸惑ってしまいました。 #1のかたのお礼にも書かせていただいたのですが new Foo(); のようにするとコンパイルは通るものの 結果が違ってきます。 どういう処理になっているのですか? 僕なりにもちょっといじって調べてみます。
補足
今色々試してみました。 すると【ここ】の部分をコメントアウトすると、 Foo Bar Hello の出力になりました。 実は回答郡に「何も記述しない」と言うのがあり 本当はそれが正解だったようです。 (この時点で誤植決定ですね・・・) で、ここで疑問になってしまったのは では、super()は何をしているのか?? と言うことです スーパークラスFooのコンストラクタを実行するものとばかり思っていました・・・ Staticのxと言う変数を定義いたしまして、プログラムのいろんな個所でインクリメントし動作を確かめたところ、 super()の時にはコンストラクタは実行されず、 Barのインスタンスを生成した時点で、一度Foo()を呼んでいるようです。 (コンストラクタの連鎖と言うんでしょうか?) で、new Foo();とするとコンストラクタがさらにもう一回呼ばれ Foo Foo となるようです。 super()はなにをしているんでしょう・・・??? 今手持ちの参考書を見たところやはり 「スーパークラスのコンストラクタを呼ぶ」 とかいてありました・・・ ????
- chi-kon
- ベストアンサー率43% (58/132)
new Foo(); はどうでしょうか
お礼
早速やってみました! コンパイルはとおりましたよ!! ありがとうございます。 ただ、実行結果が Foo Foo Bar Hello となりました。 Foo()が2回実行されているようです・・・??? なぜなんでしょう・・・??
お礼
いつも何度もありがとうございます_(._.)_ >実は、どんなクラスでもすべてのコンストラクタは必ずスーパークラスのコンストラクタを呼び出すことになっているのです。 ここのところがよくわかっていませんでした。 自動で呼ばれることはわかっているつもりでしたが、 super()を記述した場合には"もう一度”呼ばれるものだと思い込んでいました。 >Fooのインスタンスを新しく生成し、コンストラクタも実行されるのですが、変数に代入しないので、結局そのインスタンスはそのまま「あの世行き」です。 即、ガベージコレクションの対象と言うわけですね。 よくわかりました!ありがとうございました!