問題2-4
フルコースを調理するシェフを表すChefクラスを作成してください。
Chefクラスを使用するOverloadBasicPracticeクラスのmainメソッドはすでに完成しています。
(変更は禁止です)
また、各種食材を表す卵Eggクラス、米Riceクラス、牛乳Milkクラス、チーズCheeseクラスもすでに完成しています。
(変更は禁止です)
Chefクラスには、インスタンスフィールドはありません。調理を表現するcookメソッドのみが存在します。
(cookメソッドの戻り値は料理名を表すString型です)
引数で渡される食材オブジェクトに応じて書き実行結果をもとに料理を完成させてください。
【実行結果】
1品目はスクランブルエッグです 2品目はオムライスです 3品目はリゾットです 4品目はプディングです
【OverloadBasicPractice.java】
public class OverloadBasicPractice { public static void main(String[] args) { // シェフオブジェクトの生成 Chef chef = new Chef(); // 食材オブジェクトの生成 Egg egg = new Egg(); Rice rice = new Rice(); Milk milk = new Milk(); Cheese cheese = new Cheese(); // シェフがフルコースを調理します System.out.println("1品目は" + chef.cook(egg, cheese) + "です"); System.out.println("2品目は" + chef.cook(rice, egg) + "です"); System.out.println("3品目は" + chef.cook(rice, cheese) + "です"); System.out.println("4品目は" + chef.cook(milk, egg) + "です"); } } // 各種食材クラス class Egg{} class Rice{} class Milk{} class Cheese{} // ここにChefクラスを作成してください
解答例
【OverloadBasicPractice.java】
public class OverloadBasicPractice { public static void main(String[] args) { // シェフオブジェクトの生成 Chef chef = new Chef(); // 食材オブジェクトの生成 Egg egg = new Egg(); Rice rice = new Rice(); Milk milk = new Milk(); Cheese cheese = new Cheese(); // シェフがフルコースを調理します System.out.println("1品目は" + chef.cook(egg, cheese) + "です"); System.out.println("2品目は" + chef.cook(rice, egg) + "です"); System.out.println("3品目は" + chef.cook(rice, cheese) + "です"); System.out.println("4品目は" + chef.cook(milk, egg) + "です"); } } // 各種食材クラス class Egg{} class Rice{} class Milk{} class Cheese{} // Chefクラス class Chef { // 調理メソッド public String cook(Egg egg, Cheese cheese) { return "スクランブルエッグ"; } // 調理メソッド public String cook(Rice rice, Egg egg) { return "オムライス"; } // 調理メソッド public String cook(Rice rice, Cheese cheese) { return "リゾット"; } // 調理メソッド public String cook(Milk milk, Egg egg) { return "プディング"; } }
解説
今回の問題は、「オーバーロード」をしっかり理解してもらうための内容になっています。
Javaには「オーバーロード」と「オーバーライド」という似たような名前のテクニックがあります。
オブジェクト指向的に重要なのは「オーバーライド」の方で、「オーバーロード」は知っていれば便利ぐらいのものです。
クラスにはメソッドを定義できますが、普通の発想であれば1つのクラス内に同じ名前のメソッドは定義できないと考えてしまいます。
実際、1つのメソッド内に定義できるローカル変数は、名前の重複は基本的にNGです。
しかし、1つのクラスに同じ名前のメソッドを複数定義できるテクニックこそが「オーバーロード」です。
しかし、同じ名前のメソッドであっても「シグネチャ」は異なっていないといけません。
ここがポイントです。
メソッドにおける「シグネチャ」とは、メソッド名+引数の数+引数の型の組み合わせのことです。
ですので、メソッド名が同じでも引数の数と型の組み合わせが異なっていればシグネチャが異なることになるので、成立することになります。
たとえば、次のプログラムはコンパイルOKです。
class Sample { public void test(int i, String s) { } public void test(String s, int i) { } }
最初のtestメソッドは第一引数がint型、第二引数がString型になっており、2つ目のtestメソッドは第一引数がString型、第二引数がint型になっています。
これも、引数の数と型の組み合わせが異なっている(シグネチャが異なっている)ことになるので立派な「オーバーロード」です。
でも、次のような勘違いをしないようにしましょう。
このプログラムはコンパイルエラーになります。
class Sample { public void test(String abc) { } public void test(String xyz) { } }
引数名が異なっていても、シグネチャが異なることにはなりません。
あと、オーバーロードした異なるメソッドが、異なる戻り値の型でも問題ありません。
オーバーロードと戻り値の型は、全然関係がありません。
オーバーロードをうまく使うと、良いクラスに仕上がります。
しかし、メソッドをオーバーロードして良いのは、メソッドの目的が同じメソッドだけです。
全然処理が異なるメソッドをオーバーロードして、かえって混乱してしまうようなことは絶対に避けるようにしましょう。
参考図書
LINE公式アカウント
仕事が辛くてたまらない人生が、仕事が楽しくてたまらない人生に変わります。
【登録いただいた人全員に、無料キャリア相談プレゼント中!】