2003 -0228 ver 1.00 発行 -0301 ver 1.10 間違い修正 -0303 ver 1.11 誤字修正 -0304 ver 1.20 「再定義」→「多重定義」に変更 -0307 ver 1.30 多重定義のときの,引数パターンごとに定義ができるが,戻り         の違いは無視されることを追加 ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃.&&&& **** %%%%.  JavaScript&Javaで目指そう!基本情報技術者試験  ┃ ┃&&&&&&******%%%%%%  http://www.yscon.co.jp/j/java/jmaga/      ┃ ┃'&┃&''*┃*''%┃%'      (C)2003 斎藤末広 jmaga@yscon.co.jp  ┃ ┗━┻━━┻━━┻━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ 前回の発行部数 7928部(まぐまぐ:6591 melma!:753 Pubzine:475             ティアラオンライン:19 めろんぱん:90) ★解除・登録 :http://www2.odn.ne.jp/~egu33/jmaga/java-maga.html ★バックナンバー :http://www.yscon.co.jp/j/java/jmaga/ ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓  第39号 2003/02/28  メソッドの多重定義(オーバーロード)と上書き(オーバーライド) ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛  プログラムを作成する上での注意事項:  Windows98SE, SDK(JDK) 1.4.0,IE 5.5 を前提としています。  拡張子を表示するに設定してください。 ========================================================================= 交換広告(交換希望の方は,jmaga@yscon.co.jpまで) ----☆PR☆--------------------------------------------------------------           コンピュータ関係の資格を取りたい方へ              毎日届く,宿題メールの勉強仲間に入りませんか? ..&&&& **** %%%%. &&&&&&******%%%%%% 登録: http://backno.mag2.com/reader/Back?id=0000001414 '&┃&''*┃*''%┃%' 発行元:末広ページ http://3721p.com --------------------------------------------------------------☆PR☆---- ======================================================================== ▼ オーバーロードとオーバーライド  Java を勉強していると,オーバーロード,オーバーライドという紛らわしい用 語が登場します。今回は,この2つに焦点を合わせて解説をします。  オーバーロードは,over load で,積み過ぎ,という意味です。プログラム用 語としては,「多重定義」と訳されています。Jマガではオーバーロードという 用語を出来るだけ使わずに,「多重定義」を使用します。  オーバーライドは,over ride で,上に乗る,覆す,無視をする,という英語 です。プログラム用語としては,「上書き」と訳されています。Jマガでは,オー バーライドをできるだけ使わずに,「上書き」を使用します。  多重定義(オーバーロード),上書き(オーバーライド)はともに,メソッド(関 数)の定義の仕方のことです。  まずは,メソッドを利用した単純なプログラムから見ていきましょう。 ------------------------------------------------------------------------ ▼ メソッド(関数)の導入  基本プログラム,xHello.java を見てみましょう。 例 j39-01 xHello.java ソース http://www.yscon.co.jp/j/java/jmaga/j39/xHello.java 1: // Java 基本プログラム アプリケーション "Hello"を表示 2: 3: public class xHello { 4: public static void main(String xargs[]){ 5: System.out.println("Hello"); 6: } 7: }  5 行目の,System.out.println()は,長いので,新たにメソッドを導入して, 単純に名前に変更しましょう。 例 j39-02 xOvr00.java ソース http://www.yscon.co.jp/j/java/jmaga/j39/xOvr00.java 1: // printlnをシンプルに 2: // System.out.println() は長いので,xdisp()と短く 3: 4: public class xOvr00 { 5: public static void main(String xargs[]){ 6: xdisp("Hello"); 7: } 8: 9: static void xdisp(String xstr){ 10: System.out.println(xstr); 11: } 12: }  9〜11行目で,xdisp()メソッドを定義しています。これによって, 5: public static void main(String xargs[]){ 6: xdisp("Hello"); 7: }  と,System.out.println() の代わりに,xdisp() を利用することができます。  この xdisp() は,このままでは,() の中に,Stringクラスのインスタンスが 入ったときしか利用できません。xdisp(3) の様に,()の中に整数を入れると,コ ンパイルエラーとなります。  xdisp()の()の中をメソッドの引数(ひきすう)といいます。そこの引数として, 整数を入れた場合,さらに,浮動小数点を入れた場合にも対応出来るように, xOvr00.java を拡張してみましょう。 補足  浮動小数点というは,小数を含む数字のことです。精度によって,単精度と 倍精度があります。ここでは,倍精度(dobule)を使っています。 ------------------------------------------------------------------------ ▼ 多重定義(オーバーロード)の導入  disp()の引数のパターンを,文字列,整数,浮動小数点でそれぞれ動作するよ うにしました。 例 j39-03 xOvr01.java ソース http://www.yscon.co.jp/j/java/jmaga/j39/xOvr01.java 1: // xdispを引数のパターン別に定義 2: 3: public class xOvr01 { 4: public static void main(String xargs[]){ 5: xdisp("Hello"); 6: xdisp(21); 7: xdisp(0.000001); 8: } 9: 10: static void xdisp(String xstr){ 11: System.out.println(xstr); 12: } 13: 14: static void xdisp(int xi){ 15: System.out.println(xi); 16: } 17: 18: static void xdisp(double xd){ 19: System.out.println(xd); 20: } 21: }  10 〜 20 行目を見てください。同一メソッド名で,()の中が違うパターンが, 3つあります。このように,同一名のメソッドで引数のパターンの違いをいくつか 定義することを,メソッドの多重定義(オーバーロード)といいます。  メソッドの多重定義によって,同一のメソッド名で,引数のパターンごとに定 義をすることができます。  たとえば,   static void xdisp(int xi); に対して,同一のメソッド名 xdisp()で,   static void xdisp(dobule xd); // 引数が違った例 static void xdisp(int xi, yi); // 引数が違った例  と多重定義できます。 ------------------------------------------------------------------------ ▼ 継承を利用してカプセル化  xOvr01.java の,4 〜 8 行目は,xdisp() を使う部分,10 〜 20 行目は, xdisp() のメソッドを定義する部分と分かれています。他のプログラムからも, xdisp() を利用できるようにするためには,4 〜 8 行目と 10 〜 20 行目を別々 のクラスとして定義すると便利です。  次のように,メソッドの定義を一つのクラスとして独立させ,それを継承する という形にできます。 例 j39-04 xOvr02.java ソース http://www.yscon.co.jp/j/java/jmaga/j39/xOvr02.java 1: // 継承,メソッドの多重定義(オーバーロード) 2: 3: public class xOvr02 extends xDsp { // xDsp を継承 4: public static void main(String xargs[]){ 5: xdisp("Hello"); 6: xdisp(21); 7: xdisp(0.000001); 8: } 9: } 10: 11: class xDsp { 12: 13: static void xdisp(String xstr){ 14: System.out.println(xstr); 15: } 16: 17: static void xdisp(int xi){ 18: System.out.println(xi); 19: } 20: 21: static void xdisp(double xd){ 22: System.out.println(xd); 23: } 24: }  一つのソースファイルの中で,別のクラスとして独立させるだけでなく,さら に,別のソースファイルに独立させることもできます。同一フォルダに保存すれ ば特別な指定は必要ありません。 例 j39-05 xDsp.java ソース http://www.yscon.co.jp/j/java/jmaga/j39/xDsp.java  xDsp クラス 1: // Displayクラス 2: 3: public class xDsp { 4: 5: static void xdisp(String xstr){ 6: System.out.println(xstr); 7: } 8: 9: static void xdisp(int xi){ 10: System.out.println(xi); 11: } 12: 13: static void xdisp(double xd){ 14: System.out.println(xd); 15: } 16: } 例 j39-06 xOvr03.java ソース http://www.yscon.co.jp/j/java/jmaga/j39/xOvr03.java 1: // 継承,親クラス (xDsp) を外部定義 2: 3: public class xOvr03 extends xDsp { 4: public static void main(String xargs[]){ 5: xdisp("Hello"); 6: xdisp(21); 7: xdisp(0.000001); 8: } 9: }  xDsp.class が無いとき,xOvr03.java をコンパイルすれば,自動的に,xDsp.java がコンパイルされて,xDsp.class も作成されます。先に,xDsp.java をコンパイ ルしておいてもいいです。 ------------------------------------------------------------------------ ▼ 上書き(オーバーライド)の導入  xOvr03 を実行すると, Hello 21 1.0E-6  と表示されます。1.0E-6 という表示は, 1.0 に (10 の -6 乗)をかけると いう表示の仕方です。これを通常の,0.000xx の形で表示させることにしましょ う。この場合は,引数を浮動小数とする,xdisp()を別途定義をします。 例 j39-07 xOvr04.java ソース http://www.yscon.co.jp/j/java/jmaga/j39/xOvr04.java 1: // オーバーライド(上書き)の単純な例 2: 3: import java.text.DecimalFormat; 4: 5: public class xOvr04 extends xDsp { 6: public static void main(String xargs[]){ 7: xdisp("Hello"); 8: xdisp(21); 9: xdisp(0.000001); 10: } 11: 12: static void xdisp(double xd){ 13: DecimalFormat xdfmt = new DecimalFormat("#.########"); 14: System.out.println(xdfmt.format(xd)); 15: } 16: }  xdisp(浮動小数点)のときにどうするかは,xDsp の方に定義されていましたが, xOvr04.java のように,別途定義をすると,こちらの定義が有効になります。こ れを,メソッドの上書き(オーバーライド)といいます。上書き定義をするために は,同じ引数のパターン,同じ戻り値型である必要があります。もし,違っている と多重定義となります。(戻り値の型のみが違う場合はコンパイルエラーとなり ます)  上書きは,定義がしてある xOvr04 のみで,有効です。xDsp を継承している 別のクラスがあった場合には,そちらには影響はしません。  このサンプルで利用している DecimalFormat クラスは,表示するときの書式を サポートするクラスです。これを利用することで,0.00xx のように表示すること ができます。  xOvr04 を実行すると, Hello 21 0.000001  となります。 ------------------------------------------------------------------------ ▼ メソッドの多重定義(オーバーロード)と上書き(オーバーライド)の違い  メソッドの多重定義(オーバーロード)と上書き(オーバーライド)の違いをまと めてみます。 メソッドの多重定義(オーバーロード)  引数パターンが異なる形式において,同じメソッド名で多重に定義。  (戻り値の型で区別なできない) メソッドの上書き(オーバーライド)  戻り値の型,引数パターンが同じ形式の親クラスのメソッド名を上書き定義 ------------------------------------------------------------------------ ▼ コラム コンパイラの動作  2003年2月25日の宿題メールの基本情報・高度共通向けに出した宿題に,以下 のような問題がありました。  図はコンパイラにおける処理の流れを表している。a 〜 d に入る用語の組合 せとして,適切なものはどれか。 ┌──┐ ┌──┐ ┌──┐ ┌──┐ ┌───────┐ │ a │→│ b │→│ c │→│ d │→│目的コード生成│ └──┘ └──┘ └──┘ └──┘ └───────┘   ┌──────┬──────┬──────┬──────┐   │   a   │   b   │   c   │   d   │ ┌─┼──────┼──────┼──────┼──────┤ │ア│ 構文解析 │ 字句解析 │ 意味解析 │ 最適化  │ ├─┼──────┼──────┼──────┼──────┤ │イ│ 構文解析 │ 字句解析 │ 最適化  │ 意味解析 │ ├─┼──────┼──────┼──────┼──────┤ │ウ│ 字句解析 │ 構文解析 │ 意味解析 │ 最適化  │ ├─┼──────┼──────┼──────┼──────┤ │エ│ 字句解析 │ 構文解析 │ 最適化  │ 意味解析 │ └─┴──────┴──────┴──────┴──────┘ ■キーワード■ コンパイラ ■解答■   ソフトウェア開発技術者午前平成13年問44   ┌──────┬──────┬──────┬──────┐   │   a   │   b   │   c   │   d   │ ┌─┼──────┼──────┼──────┼──────┤ │ウ│ 字句解析 │ 構文解析 │ 意味解析 │ 最適化  │ └─┴──────┴──────┴──────┴──────┘  コンパイラは,  字句解析   ↓  構文解析   ↓  意味解析   ↓  最適化   ↓  コード生成  の順で処理します。  Java のコンパイルではどうか見てみましょう。  Javac でコンパイルのときに,-verbose をつけると,コンパイルの途中経過が 表示されます。 例 j39-06 xOvr03.java ソース http://www.yscon.co.jp/j/java/jmaga/j39/xOvr03.java 1: // 継承,親クラス (xDsp) 外部定義 2: 3: public class xOvr03 extends xDsp { 4: public static void main(String xargs[]){ 5: xdisp("Hello"); 6: xdisp(21); 7: xdisp(0.000001); 8: } 9: }  -verboes 付きでコンパイルすると次のようにメッセージが表示されます。 S:\ftpyscon\j\java\jmaga\j39>javac -verbose xOvr03.java [xOvr03.java を構文解析開始] [170ms で構文解析完了] [.\xDsp.class を読み込み中] [C:\J2SDK1.4\JRE\lib\rt.jar(java/lang/Object.class) を読み込み中] [C:\J2SDK1.4\JRE\lib\rt.jar(java/lang/String.class) を読み込み中] [xOvr03 を確認中] [xOvr03.class を書き込み完了] [合計 830ms]  ここで,構文解析開始,構文解析完了のところで,字句解析,構文解析を やっています。意図的に,エラーを出してみましょう。  3 行目のpublic を 次のように p@blic として,コンパイルしてます。 1: // 継承,親クラス (xDsp) 外部定義 2: 3: p@blic class xOvr03 extends xDsp { 4: public static void main(String xargs[]){ 5: xdisp("Hello"); 6: xdisp(21); 7: xdisp(0.000001); 8: } 9: } S:\ftpyscon\j\java\jmaga\j39>javac -verbose xOvr03.java [xOvr03.java を構文解析開始] xOvr03.java:3: 'class' または 'interface' がありません。 p@blic class xOvr03 extends xDsp { ^ xOvr03.java:3: \64 は不正な文字です。 p@blic class xOvr03 extends xDsp { ^ [170ms で構文解析完了] [.\xDsp.class を読み込み中] [C:\J2SDK1.4\JRE\lib\rt.jar(java/lang/Object.class) を読み込み中] [C:\J2SDK1.4\JRE\lib\rt.jar(java/lang/String.class) を読み込み中] [xOvr03 を確認中] [合計 660ms] エラー 2 個  字句解析はして,p,@,blic,と順に字句が取り出せたようです。字句解析が おわり,@ は,不正な文字であると叱れました。このエラーは,字句解析のエ ラーか構文解析のエラーか不明です。  xOvr03.java:3: 'class' または 'interface' がありません。  は,構文解析のエラーです。文法上のエラーを調べるのが,構文解析です。 [xOvr03 を確認中]  は意味解析中という意味です。意味解析というのは,文法としては正しいが, 他との整合性を解析します。文法としては正しいが,コンパイルは通らないエラー を出してみましょう。  先ほどの p@blic は,正しくして,xDsp.java の方の方に修正しましょう。  xdisp()の引数は,文字列,整数,浮動小数点が,xDsp.java で定義されていま した。xDsp.java の文字列の定義のところをコメントにして,引数が文字列の場合 の,xdisp() を無くしてみましょう。そうすることで,文法としては正しいですが, 整合性がとれなくなるはずです。 // Displayクラス public class xDsp { /* コメントで,無効にする。 static void xdisp(String xstr){ System.out.println(xstr); } */ static void xdisp(int xi){ System.out.println(xi); } static void xdisp(double xd){ System.out.println(xd); } }  xDsp.java を修正したので,こちらを先にコンパイルをかけてから, xOvr03.java をコンパイルをします。そうすると, S:\ftpyscon\j\java\jmaga\j39>javac -verbose xOvr03.java [xOvr03.java を構文解析開始] [110ms で構文解析完了] [.\xDsp.class を読み込み中] [C:\J2SDK1.4\JRE\lib\rt.jar(java/lang/Object.class) を読み込み中] [C:\J2SDK1.4\JRE\lib\rt.jar(java/lang/String.class) を読み込み中] [xOvr03 を確認中] xOvr03.java:5: シンボルを解釈処理できません。 シンボル: メソッド xdisp (java.lang.String) 位置 : xOvr03 の クラス xdisp("Hello"); ^ [合計 660ms] エラー 1 個  となりました。 [xOvr03 を確認中] xOvr03.java:5: シンボルを解釈処理できません。  は,意味解析のエラーです。構文解析の後に,意味解析がされていることが分 かりました。  xDsp.java を元に戻して,もう一度コンパイルをやり直します。 S:\ftpyscon\j\java\jmaga\j39>javac -verbose xOvr03.java [xOvr03.java を構文解析開始] [160ms で構文解析完了] [.\xDsp.class を読み込み中] [C:\J2SDK1.4\JRE\lib\rt.jar(java/lang/Object.class) を読み込み中] [C:\J2SDK1.4\JRE\lib\rt.jar(java/lang/String.class) を読み込み中] [xOvr03 を確認中] [xOvr03.class を書き込み完了] [合計 770ms]  「xOvr03.class を書き込み完了」のメッセージのところは,ここで,コード の生成が終わり,それがファイルして書き出されたことを表しています。通常 この直前に最適化が終了しています。 ------------------------------------------------------------------------ ▼ コラム 配列の[]  配列の宣言の仕方は,String配列のxargsを例とすると  String[] xargs;  String []xargs;  String xargs[]; の3通りの書き方があります。真ん中の書き方は,あまり普及していませんので これ以上触れません。一番上が,現在,Java のプログラムスタイルとして普及し ています。最後の書き方は,他の言語で従来から書かれているパターンです。  この2通りのパターンを利用して,2次元配列を宣言すると,  String[][] xargs;  String xargs[][];  String[] xargs[]; のように,宣言できます。xargs が,2次元配列であると一番はっきるするのは 二つ目のように思われます。よって,Jマガでは,配列の宣言の仕方は,  String xargs[];  のように,配列名の後ろに[]を付けるを標準とすることします。  --Jマガローカル規則 -------------------------------------  配列の定義のときの[] の位置   型 変数名[];  クラス インスタンス名[]  理由,2次元配列のときに間違いが発生しにくい。  ==================================== Jマガローカル規則 == ------------------------------------------------------------------------ ▼ 次号の予定  次号では,インスタンスメソッド,クラスメソッド  知りたいテクニック,また,解説してほしいクラスなどリクエストお寄せくだ さい。 ------------------------------------------------------------------------ ▼ 著作権について  このメールマガジンで公開しているプログラムソースは,著作権を当方スタッ フが所有しますが,プログラムソースの利用は,商用を含めて,再利用,改変, 発表を制限しません。  画像や音などの素材は,それぞれ著作権があります。著作者に承諾なしに再利 用はできません。  本文に関しては,斎藤末広が著作権を所有します。再利用に関しては,承諾を 必要とします。 ------------------------------------------------------------------------ ▼アンケート(以下を返信してください)  この号のJマガに対するご意見をお待ちしています。ぜひ,ご返信下さい。 この号の内容 1 良かった 2 普通 3 良くなかった コメント,リクエストもどうぞ。