Comments
Description
Transcript
コンピュータプログラミング B 補助教材(18)
コンピュータプログラミング B 補助教材(18) 授業第 19 回 2016.06 前回課題について(第 18 回) 課題 1オンラインドキュメント 7.9 章の B7_5.java をよく読んで理解し,何が表示されるか予 測した上,打ち込んでコンパイル,実行を行い,予測と一致するか確かめなさい. 解答例 (参考)B7_5.java 1 importjava.util.ArrayList; 2 3 publicclassB7_5{ 4 publicstaticvoidmain(String[]args){ 5 ArrayList<Educatee>arrayList=newArrayList<Educatee>(); 6 Educateeeducatee1=newEducatee("001ID00","nakamura"); 7 arrayList.add(educatee1); 8 educatee1.setHeight(170); 9 Educateeeducatee2=arrayList.get(0); 10 booleanb=(educatee1==educatee2); 11 System.out.println(b); 12 System.out.println(educatee1.getHeight()); 13 System.out.println(educatee2.getHeight()); 14 } 15 } 解答例(S 君) [予測] 「boolean」に代入させることが出来るのは,真か偽のみであり,「b」に入る値は, 「educatee1==educatee2」という条件式の真偽である. このプログラム上では,Educatee の型で educatee1 を宣言し,値を代入した.その後,arrayList の一番目に educatee1 と同じ内 容のオブジェクトを追加した.ただしこの時,educatee1 と同じオブジェクトがもう一つ出来た わけではなく.arrayList の一番目には educatee1 のオブジェクトを呼び出す為の番地が記録さ れただけである.よって,setHeight()によって educatee1 の中の中身が変えられたとしても呼 び出すオブジェクトは educatee1 なため「arrayList(0)」(arrayList の一番目)を代入された 「educatee2」は名前こそ違うものの,呼び出すオブジェクトは「educatee1」に変わりない.こ れらの事から,変数「b」に代入される値は「true」となる. 次に,「System.out.println()」 で指定されている educatee1.getHeight()と educatee2.getHeight()についてだが,上記で説明 18-1 した通り,この二つが指しているオブジェクトは同一なので,得られる値も同じ「170」である. 以上のことからコマンドプロンプト上に表示されるのは, true 170 170 だと私は予 測した. [コンパイル&実行結果] >javacB7_5.java >javaB7_5true170170 解説 6 行目の右辺では Educatee 型のオブジェクトができます.その参照情報(番地)は左辺 の educatee1 に代入されます.7 行目ではこれを arrayList の管理対象に加えます.実際には最 初のものなので 0 番目にこの参照情報(オブジェクトがどこに保存されているかの番地情報)が 入ります.8 行目ではくだんのオブジェクトに setHeight(170)によって height を 170 とするよ うに指示します.9 行目では arrayList.get(0)によって arrayList の 0 番目の要素を取り出しそ れを左辺に入れます.arrayList はオブジェクトのコピーを保存しているのでなくオブジェクト の参照情報を保持しているだけなので左辺の educatee2 は依然として最初のオブジェクトの参 照情報を持っています.よって educatee2 と educatee1 は同一の参照情報を持っています. educatee1 と educatee2 が同じオブジェクトを指していることを理解することが重要です.従っ て 10 行目右辺では同一と判定されます.その左辺は true となります.12,13行目は同一のオ ブジェクトに対しgetHeight()が出されるのでいずれも 170 が表示されます. 課題 2(7.11 章演習 7-2)B7_7 を参考にプログラムを作り,オブジェクト図の状態になるように しなさい.また,それぞれのオブジェクトの身長とパスワードを表示するようにしなさい. 解答例 B7_71.java 1 importjava.util.ArrayList; 2 3 publicclassB7_71{ 4 publicstaticvoidmain(String[]args){ 5 ArrayList<Educatee>arrayList=newArrayList<Educatee>(); 6 arrayList.add(newEducatee("00ID00","nakamura")); 7 arrayList.add(newEducatee("00IE00","iimura")); 8 Educateeeducatee1=arrayList.get(0); 9 educatee1.setPassword("pass1"); 10 educatee1.setHeight(170); 11 Educateeeducatee2=arrayList.get(1); 18-2 12 educatee2.setPassword("pass2"); 13 educatee2.setHeight(175); 14 for(inti=0;i<arrayList.size();i++){ 15 Educateeeducatee=arrayList.get(i); 16 System.out.println(educatee.getName()); 17 System.out.println(educatee.getId()); 18 System.out.println(educatee.getPassword()); 19 System.out.println(educatee.getHeight()); 20 } 21 } 22 } [結果] >javaB7_70 nakamura 00ID00 pass1 170 iimura 00IE00 pass2 175 コメント 6 arrayList.add(newEducatee("00ID00","nakamura")); で arrayList に新たに作った Educatee のオブジェクトを入れています. 7 行目も同様です. オブ ジ ェ ク ト 図 に あ る よ う に パ ス ワ ー ド や height を 設 定 す る に は そ れ ら の オ ブ ジ ェ ク ト に setPassword, setheight で働き掛ける必要があります. そのためにはそれらのオブジェクトへの参 照を得る必要があります. プログラムの 7 行目までは改変できないため arrayList から取り出すし かありません. それらは arrayList の 0, 1 番目に入っていることが分っているので 8, 11 行目で取 り出しています. 課題 3次の手順で EducateeList のプログラムを作りなさい. (1)7.13 章にある EducateeList のクラス図からプログラムを機械的に導出しなさい. 解答例 EducateeList.java 18-3 1 importjava.util.ArrayList; 2 3 publicclassEducateeList{ 4 privateArrayList<Educatee>arrayList=newArrayList<Educatee>(); 5 publicEducateeList(){ 6 } 7 publicvoidadd(Educateeeducatee){ 8 } 9 publicEducateeget(intnumber){ 10 11 } 12 publicintgetAverageHeight(){ 13 14 } 15 publicintsize(){ 16 17 } 18 } returnnull; return0; return0; (2)EducateeList のクラス図と API 仕様を用いて EducateeList のプログラムを完成し B7_9 によ って動作を確認しなさい. 解答例 EducateeList.java 1 importjava.util.ArrayList; 2 3 publicclassEducateeList{ 4 privateArrayList<Educatee>arrayList=newArrayList<Educatee>(); 5 publicEducateeList(){ 6 } 7 publicvoidadd(Educateeeducatee){ 8 this.arrayList.add(educatee); 9 } 10 publicEducateeget(intnumber){ 11 returnthis.arrayList.get(number); 18-4 12 } 13 publicintgetAverageHeight(){ 14 intaverageHeight=0; 15 for(inti=0;i<this.arrayList.size();i++){ 16 Educateeeducatee=this.arrayList.get(i); 17 averageHeight=averageHeight+educatee.getHeight(); 18 } 19 averageHeight=averageHeight/this.arrayList.size(); 20 returnaverageHeight; 21 } 22 publicintsize(){ 23 returnthis.arrayList.size(); 24 } 25 } 結果(B7_9) >>javaB7_9 平均身長:172 コメント 大体いつものパターンです.13-21 行目の getAverageHeight はよくある合計を求め るメソッド(振る舞い)とほんの少しだけ違います.平均は合計を個数で割れば得られるという ことは覚えておいてください.整数同士の割算を行うと小数点以下は切り捨てです.実用上は 問題がありますがこの授業ではよしとしています(授業範囲外ですが double を使えば小数点以 下も扱えます).EducateeList については同種のプログラムをこれまでのべ 7〜8 回は書いたは ずです.すらすら答が書けないようなら徹底的に復習が必要です.形だけ記憶するのでなく意 味を理解するようにしてください.不明な点は遠慮なく質問するようにしてください. 上でアンダーラインした部分は内部の状態の引用です.このような場合必ず this.を付ける ようにしてください.実際のプログラムは this を付けなくても同じ結果が得られる場合が多い のですがこの授業では状態の引用には this.を付けるをルールとしています.試験時には守ら ないと意外と多く減点されます(2〜3 ヶ所怠ると成績が一段階下がる程度). 一口メモ toString の効用(範囲外) 解答例 B7_71 で使っている Educatee に例を取って toString の使い方を説明します.Educatee に次のメソッド(振る舞い)を追加します. publicStringtoString(){ 18-5 return"id="+this.id+"password="+this.password +"name="+this.name+"height="+this.height; } B7_71 を若干変更して下記とします. B7_72.java 1 importjava.util.ArrayList; 2 3 publicclassB7_72{ 4 publicstaticvoidmain(String[]args){ 5 ArrayList<Educatee>arrayList=newArrayList<Educatee>(); 6 arrayList.add(newEducatee("00ID00","nakamura")); 7 arrayList.add(newEducatee("00IE00","iimura")); 8 Educateeeducatee1=arrayList.get(0); 9 educatee1.setPassword("pass1"); 10 educatee1.setHeight(170); 11 Educateeeducatee2=arrayList.get(1); 12 educatee2.setPassword("pass2"); 13 educatee2.setHeight(175); 14 for(inti=0;i<arrayList.size();i++){ 15 Educateeeducatee=arrayList.get(i); 16 System.out.println(educatee); 17 } 18 } 19 } 実行結果 >javaB7_72 id=00ID00password=pass1name=nakamuraheight=170 id=00IE00password=pass2name=iimuraheight=175 若干表示形式は異なりますがプログラムの手間が省けます.System.out.println(educatee);と するだけで educatee オブジェクトの toString が呼び出されてその状態を表示できます.授業に 出てくるクラスに自由に toString を追加して構いません.(加えても悪さはしません.試験の ときは遠慮してください) 一口メモ static の付いたメソッド(範囲外) 18-6 main のメソッド(振る舞い)には publicstaticvoidmain(String[]args) のように static が付いていました.またコンピュータプログラミング A で学んだメソッドには すべて static が付いていたはずです.ここでその種明かしをします.static の付いていないメ ソッドは,オブジェクトが作られるときに一緒に付いてきます.よってオブジェクトへの参照 が object なら object.メソッド名で呼び出すことができます.もしオブジェクトが作られてい なければクラスファイルをコンパイル済でも呼び出すことはできません.これに対し static の 付いているメソッドはクラスファイルがコンパイル済ならクラス名.メソッド名で呼び出すこと ができます(クラス内部からならメソッド名だけで呼び出し可能).いわばクラスに付随してい るのでクラスメソッドとも呼ばれます.あるクラスが複数のオブジェクトを持つとき,何個の オブジェクトができているのかを知りたいことがあります.またオブジェクト間の情報をクラ ス内部で知りたいこともあります.このようなときは static の付いたクラスメソッドを使いま す.main は必ず static にします.そうすると javaクラス名としたとき,ルールに従って main を探し,そこから起動します.static はオブジェクトを(改めて)作らなくともすぐに動きま す. インタフェース(復習と補足) Java 言語ではインタフェースは別々のクラスのものを見かけ上同じ型として扱える仕組みです. また実際のクラスファイルの中身を作る前にその骨格部分をインタフェースとして先に作って おく(抽象的に作る)こともあります.インタフェースはプログラムの形式上ではクラスに似て います(まとめて呼ぶときは参照型と呼びます.なおプログラム階層というものがありパッケ ージ>クラス,インタフェース となっておりクラスとインタフェースはプログラム階層上同 一といいます).インタフェースはクラスを抽象化したものと説明されることがあります.形式 上インタフェース(宣言)のプログラムは: publicinterfaceインタフェース名{ public戻り値の型名 振る舞い名(); } と書きます.(ここに public としたものは当分の間こうします)クラスのプログラムを簡略化し たような形式になっています.ただし,インタフェースの振る舞い部分は{}がありません (これは実態がないことを意味し,抽象化されているといいます).インタフェースのプログラ ムはそのインタフェース名で呼ばれる実体のプログラム(仲間)がいることとそのインタフェー スには宣言した振る舞いが存在することを宣言します(コンパイル後有効になります). インタフェースの実装 宣言されたインタフェースを引用して使うことを実装するといいます. publicclassクラス名implementsインタフェース名{ 18-7 . } この形式は通常のクラスのプログラムに似ていますが implementsインタフェース名の部分が 異なっています.このように実装した場合,このクラスの型名はインタフェース名として扱う ことができます(例 Dice,EvenDice,OddDice は Castable を実装することにより,いずれも Castable 型の変数として扱える).インタフェースを実装したクラスは必ずインタフェースで宣 言された振る舞いを持たなくてはなりません(そうでないとコンパイル時にエラーになります). インタフェース型の変数 この授業においては,インタフェースを実装したクラスのオブジェクトへの参照を保存する変 数の定義は: イ ン タ フ ェ ー ス 型 変 数 名 のようにすると記憶しておいてください.クラス名変数名でも 保存はできますがインタフェースが同一の複数のクラスを扱うとき,矛盾をきたすためです. 1 publicclassB8_1{ 2 publicstaticvoidmain(String[]ags){ 3 Ballball1=newConcreteBall(1); 4 Ballball2=newConcreteBall(2); 5 System.out.println(ball1.getNumber()); 6 System.out.println(ball2.getNumber()); 7 } 8 } 上記のプログラムで 3,4 行目に着目してください.いずれも右辺で ConcreteBall が呼ばれ,右 辺の値は ConcreteBall オブジェクト(インスタンス)への参照になります.これを左辺に代入 しますが,ConcreteBall は Ball インタフェースを実装しているため,Ball 型のデータとして扱 えることから左辺はこのようにしています.このプログラム限りでは 3 ConcreteBallball1=newConcreteBall(1); 4 ConcreteBallball2=newConcreteBall(2); としても動くことは動きます,しかし上記の原則に従ってこのように Ballball1 のようにしま す.ConcreteBall のオブジェクト(インスタンス)への参照は ConcreteBall 変数に代入でき ますが,Ball の型名の変数に入れることもできます.つまり ConcreteBall オブジェクトは ConcreteBall としての素の顔のほかにインタフェース Ball の顔も持つことができます.もし別 の Ball インタフェースを実装しているクラスがあれば,そのオブジェクトへの参照を同様に Ball 型変数に代入できます.つまり Ball インタフェースを通じて別々のクラスのオブジェクト 18-8 <<interface>> Ball getNumber() : int ConcreteBall number:int ConcreteBall(number:int) getNumber() : int への参照が同一の型の変数で扱えます(混在できる).インタフェースは異なるクラスを束ねる ことができるので,それを実装するクラスのオブジェクトへの参照をインタフェース型で定義 するのは自然です.なお,1 つのクラスは複数のインタフェースを実装することができます.よ って一般には目的に応じて変数の型名をきめる必要があります.インタフェースを実装する複 数のクラスがあると思えますが,この授業で扱う例では 1 つだけで終っている場合も多いです. インタフェースはクラスを作る前に先に抽象的にプログラムを定義する手法でもあるのでその 例と考えてください. 任意課題 1(1)解答例(Footwear のクラス図からプログラムを作る) Footwear.java 1 publicinterfaceFootwear{ 2 publicStringgetName(); 3 publicintgetSize(); 4 publicintgetPrice(); 5 } 任意課題 1(2)解答例(Boot のクラス図と API からプログラムを作る) Boot.java 1 publicclassBootimplementsFootwear{ 18-9 2 privateStringname=“靴”; 3 privateintsize; 4 privateintprice; 5 publicBoot(intsize,intprice){ 6 this.size=size; 7 this.price=price; 8 } 9 publicStringgetName(){ 10 11 } 12 publicintgetSize(){ 13 14 } 15 publicintgetPrice(){ 16 17 } 18 } returnthis.name; returnthis.size; returnthis.price; 任意課題 2(1)解答例(Boot 検証用プログラム)B8_11.java 1 publicclassB8_11{ 2 publicstaticvoidmain(String[]args){ 3 Bootfootwear1=newBoot(25,10000); 4 Bootfootwear2=newBoot(30,30000); 5 System.out.println(footwear1.getName()+""+footwear1.getSize() +""+footwear1.getPrice()); 6 System.out.println(footwear2.getName()+""+footwear2.getSize() +""+footwear2.getPrice()); 7 8 } 9 } 実行結果>javaB8_11 靴2510000 靴3030000 任意課題 2(2)(Zouri,Geta のプログラム)略 18-10 任意課題 2(3)解答例(FootwearBox などのプログラムを作る)(HC さん) FootwearBox.java 1 importjava.util.ArrayList; 2 3 publicclassFootwearBox{ 4 privateArrayList<Footwear>arrayList=newArrayList<Footwear>(); 5 publicFootwearBox(){ 6 7 } 8 publicvoidadd(Footwearfootwear){ 9 10 } 11 publicFootwearget(intnumber){ 12 13 } 14 publicintgetPriceSum(){ 15 intsum=0; 16 for(inti=0;i<this.arrayList.size();i++){ 17 Footwearfootwear=this.arrayList.get(i); 18 sum=sum+footwear.getPrice(); 19 } 20 returnsum; 21 } 22 publicintsize(){ 23 24 } 25 publicFootwearremove(intnumber){ 26 27 } 28 } this.arrayList.add(footwear); returnthis.arrayList.get(number); returnthis.arrayList.size(); returnthis.arrayList.remove(number); 検証用プログラムTestFootwearBox.java 1 publicclassTestFootwearBox{ 2 publicstaticvoidmain(String[]args){ 18-11 3 FootwearBoxfootwearBox=newFootwearBox(); 4 footwearBox.add(newBoot(26,15000)); 5 footwearBox.add(newZouri(23,2000)); 6 footwearBox.add(newGeta(25,8000)); 7 for(inti=0;i<footwearBox.size();i++){ 8 Footwearfootwear=footwearBox.get(i); 9 System.out.println(footwear.getName() + " サ イ ズ は " + footwear.getSize()+"cm、価格は"+footwear.getPrice()+"円です"); 10 } 11 System.out.println("価格の合計は"+footwearBox.getPriceSum()+" 円で、靴箱の中身は"+footwearBox.size()+"足です"); 12 Footwearfootwear=footwearBox.remove(1); 13 System.out.println(footwear.getName()+"を削除すると靴箱の中身は" +footwearBox.size()+"足になります"); 14 } 15 } 実行結果 >javaTestFootwearBox 靴サイズは 26cm、価格は 15000 円です 草履サイズは 23cm、価格は 2000 円です 下駄サイズは 25cm、価格は 8000 円です 価格の合計は 25000 円で、靴箱の中身は 3 足です草履を削除すると靴箱の中身は 2 足に なります ビンゴカード 18-12