質問: new ArrayList(); } public void addChild(Layout layout){ child.add(layout); } public void flush(){ System.out.println("" + getTag() + ">"); for(Layout c:child){ c.flush(); } System.out.println("" + getTag() + ">"); } String getTag(){ return tag; } } class GridLayout extends LayoutBase{ String getTag(){ return "GridLayout"; } } class FlowLayout extends LayoutBase{ String getTag(){ return "FlowLayout"; } } ``` ### 実行結果
回答: 下のコード内で説明して見ました 番号順に説明してあります ``` import java.util.ArrayList; import java.util.List; public class Sample { public static void main(String[] args){ //1LayoutBaseオブジェクトのインスタンスを変数layoutに入れる //この時、new LayoutBase() してLayoutBaseオブジェクトのインスタンスを作成した時に //LayoutBaseクラスのコンストラクタである public LayoutBase(){}が呼ばれ //予めLayoutBaseクラス内で宣言されていた List 型の変数child内に //new ArrayList() が代入される LayoutBase layout = new LayoutBase(); //2layout変数に入っているLayoutBaseオブジェクトのインスタンス内のaddChild()メソッドを呼び出す //引数にnew GridLayout(),new FlowLayout()を入れて二回実行する //この時、addChildメソッドの引数は public void addChild(Layout layout){のように //Layout型になっているため このメソッドの引数にはポリモーフィズムを用い //Layoutインターフェースをimplementsしたクラスを入れて呼び出す事ができる //二回呼び出した結果addChild内の操作により // List 型の変数child内のインスタンスnew ArrayList()内に //new GridLayout()・・・・クラスGridLayoutのインスタンスと //new FlowLayout()・・・・クラスFlowLayoutのインスタンスが一つずつ入る layout.addChild(new GridLayout()); layout.addChild(new FlowLayout()); //3layout変数に入っているLayoutBaseオブジェクトのインスタンス内のflush()メソッドを呼び出す //flushメソッド内での操作は //・・・・4に続く layout.flush(); } } interface Layout{ void addChild(Layout layout); void flush(); } class LayoutBase implements Layout{ String tag = "root"; Listchild; public LayoutBase(){ child = new ArrayList(); } public void addChild(Layout layout){ child.add(layout); } public void flush(){ //4 と > の間にメソッドgetTag()の返り値が結合されて表示され改行される //getTag()の返り値とはString tag = "root";で代入されている値root //よってが表示される System.out.println("" + getTag() + ">"); //5拡張for文により変数child内に入っているインスタンスが順にLayout型の変数cに代入されて{}内で実行される //c.flush();により各インスタンス内のflushメソッドが呼び出されるが、 //flushメソッドは各オブジェクト(GridLayout,FlowLayout)ではオーバーライドされておらず、 //それらが共通でextendsしているクラスLayoutBaseのみでオーバーライドされている //よって、これらのオブジェクトが入っているLayout型変数cからflushメソッドを呼び出した場合 //ポリモーフィズムの働きによりLayoutBase内でオーバーライドされたflushメソッドが実行され //その呼び出されたそれぞれのオブジェクト(GridLayout,FlowLayout)内のflushメソッドは //その内部で と > の間にメソッドgetTag()の返り値が結合されて表示し改行する //この時、メソッドgetTag()はそれぞれのオブジェクト(GridLayout,FlowLayout)内でオーバーライドされており、 //GridLayout内メソッドのgetTag()では"GridLayout",FlowLayoutメソッドのgetTag()では"FlowLayout" //を返す //その後それぞれのオブジェクト(GridLayout,FlowLayout)内のflushメソッドは // for(Layout c:child){ // c.flush(); // } //部分を実行しようとするが、この時GridLayout,FlowLayoutそれぞれのオブジェクト内では一度もaddChildメソッドが実行されていないので //これらのオブジェクト内のListchild;にはGridLayout,FlowLayoutそれぞれのオブジェクトの生成時のコンストラクタの動作 //により生成されたnew ArrayList()が入っているだけでこのインスタンス内には値が入っていない よって //上記拡張for文内では何も表示されず //その後のSystem.out.println("" + getTag() + ">");により // と > の間にメソッドgetTag()の返り値 すなわち //GridLayout内メソッドのgetTag()では"GridLayout",FlowLayoutメソッドのgetTag()では"FlowLayout"が結合されて表示され改行される //これらがそれぞれのオブジェクト内にて順に実行され // // // // //と表示された後 //上の5先頭部分の拡張for文を抜けて次の文に進み // と > の間にメソッドgetTag()の返り値が結合されて表示され改行される //getTag()の返り値とはこの場合String tag = "root";で代入されている値root //よってが表示される //ここでmainメソッドで呼び出したflushメソッドが終了しmainメソッドが終わりプログラムは終了する for(Layout c:child){ c.flush(); } System.out.println("" + getTag() + ">"); } String getTag(){ return tag; } } class GridLayout extends LayoutBase{ String getTag(){ return "GridLayout"; } } class FlowLayout extends LayoutBase{ String getTag(){ return "FlowLayout"; } } ```