クラス実装問題集逆引き目次(クラス実装問題:ポケモン編)
- ポケモンクラスの基本実装
- ポケモンクラスの継承(LegendaryPokemon)
- オーバーライドでTrainer情報追加
- インターフェースの実装(Displayable)
- 進化メソッド evolve() の追加
- if文・for文・配列を使った技習得処理
- Pikachuクラスの実装(Pokemonを継承)
- Raichuクラスの実装(Pikachuを継承)
- Eeveeクラスの実装(Pokemonを継承)
- Squirtleクラスの実装(Pokemonを継承)
- Pokemonクラスのレベル機能リファクタリング
- リファクタリングによるサブクラスへの影響
- 最終版Pokemonクラスの統合例
前提
今回、Pokemon.javaを作成し、 Pokemon クラスを実装していきます。
Pokemon.javaで用意した Pokemon クラスを実行するためには、Main.javaのような Main クラスを用意する必要があります。
まだ level や evolve、learnMoves を実装していない段階の Pokemon を試したい場合は、その段階に合わせて Main 内の呼び出しをコメントアウトするか削除してください。
public class Main {
public static void main(String[] args) {
// 1. 基本的な情報表示
Pokemon p = new Pokemon();
p.setName("Pikachu");
p.setType("Electric");
p.setLevel(5); // レベル機能を実装している場合
System.out.println("基本情報: " + p.getInfo());
System.out.println("現在レベル: " + p.getLevel());
// 2. 進化メソッドの動作確認
p.evolve("Raichu");
// 3. 技習得メソッドの動作確認
String[] moves = {"Thunderbolt", "Quick Attack", "Iron Tail"};
p.learnMoves(moves);
// 4. レベルアップ処理の確認
p.levelUp(); // 1 レベルアップ
System.out.println("レベルアップ後のレベル: " + p.getLevel());
}
}
1. ポケモン継承なし例
Pokemon クラスの作成
以下の仕様に従って Pokemon クラスを作成してください。
フィールド
-
name(型: String): ポケモンの名前 -
type(型: String): ポケモンのタイプ
メソッド
-
getName(): 名前を返す -
setName(String name): 名前を設定する -
getType(): タイプを返す -
setType(String type): タイプを設定する -
getInfo():"Pikachu (Electric)"のような形式でnameとtypeを出力する文字列を返す
出力例
入力値
Pokemon p = new Pokemon();
p.setName("Pikachu");
p.setType("Electric");
System.out.println(p.getInfo());
出力値
Pikachu (Electric)
解答コード例
public class Pokemon {
private String name;
private String type;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getInfo() {
return name + " (" + type + ")";
}
}
2. ポケモン継承あり例
Pokemon クラス
- 前問と同じ仕様
LegendaryPokemon クラスの作成
Pokemon クラスを継承した LegendaryPokemon クラスを作成してください。
フィールド
-
region(型: String): 発見された地方名(例: "Kanto")
メソッド
-
getRegion(): 地方名を返す -
setRegion(String region): 地方名を設定する -
getInfo():"Pikachu (Electric) - Region: Kanto"のようにPokemonの情報に地域名を追加した形式で返す
出力例
入力値
LegendaryPokemon lp = new LegendaryPokemon();
lp.setName("Pikachu");
lp.setType("Electric");
lp.setRegion("Kanto");
System.out.println(lp.getInfo());
出力値
Pikachu (Electric) - Region: Kanto
解答コード例
public class LegendaryPokemon extends Pokemon {
private String region;
public String getRegion() {
return region;
}
public void setRegion(String region) {
this.region = region;
}
@Override
public String getInfo() {
return super.getInfo() + " - Region: " + region;
}
}
3. ポケモン継承とoverrideあり例
TrainerPokemon クラスの作成
Pokemon クラスを継承した TrainerPokemon クラスを作成してください。
フィールド
-
trainerName(型: String): トレーナーの名前
メソッド
-
getTrainerName()/setTrainerName(String trainerName) -
getInfo()をオーバーライドし、"[Ash] Pikachu (Electric)"の形式で返す
出力例
入力値
TrainerPokemon tp = new TrainerPokemon();
tp.setName("Pikachu");
tp.setType("Electric");
tp.setTrainerName("Ash");
System.out.println(tp.getInfo());
出力値
[Ash] Pikachu (Electric)
解答コード例
public class TrainerPokemon extends Pokemon {
private String trainerName;
public String getTrainerName() {
return trainerName;
}
public void setTrainerName(String trainerName) {
this.trainerName = trainerName;
}
@Override
public String getInfo() {
return "[" + trainerName + "] " + super.getInfo();
}
}
4. ポケモン継承とoverrideとインターフェイスあり例
Displayable インターフェイス
-
display()メソッドを定義する
実際のプロジェクトでは、
DisplayableとBattlePokemonは別ファイルに分けて定義してください。
(ここでは説明のため 1 つのコードブロックにまとめています)
BattlePokemon クラスの作成
Pokemon を継承し、Displayable インターフェイスを実装する BattlePokemon クラスを作成してください。
フィールド
-
level(型: int): レベル
※この段階では、Pokemon側にはlevelはまだありません。
後半の「7. リファクタリング」で、Pokemon自体にレベルを追加します。
メソッド
-
getLevel()/setLevel(int level) -
getInfo()をオーバーライドし、"Pikachu (Electric) - Lv.25"の形式で返す -
display()メソッドを実装し、"Displaying: Pikachu"を出力する
出力例
入力値
BattlePokemon bp = new BattlePokemon();
bp.setName("Pikachu");
bp.setType("Electric");
bp.setLevel(25);
System.out.println(bp.getInfo());
bp.display();
出力値
Pikachu (Electric) - Lv.25
Displaying: Pikachu
解答コード例
public interface Displayable {
void display();
}
public class BattlePokemon extends Pokemon implements Displayable {
private int level;
public int getLevel() {
return level;
}
public void setLevel(int level) {
this.level = level;
}
@Override
public String getInfo() {
return super.getInfo() + " - Lv." + level;
}
@Override
public void display() {
System.out.println("Displaying: " + getName());
}
}
クラス追加実装問題集(ポケモン編)
1. ポケモンクラスに、進化メソッド(evolve)を追加
Pokemon クラスの拡張
以下の仕様に従って、Pokemon クラスに evolve() メソッドを追加してください。
既存フィールド
-
name(型: String): ポケモンの名前 -
type(型: String): ポケモンのタイプ
追加メソッド
-
evolve(String newName)- 引数で渡された
newNameを使って名前を進化後の名前に変更します - 変更後の名前とタイプを
"進化後: Raichu (Electric)"のように表示する形式でSystem.out.println()で出力します。
- 引数で渡された
出力例
入力値
Pokemon p = new Pokemon();
p.setName("Pikachu");
p.setType("Electric");
p.evolve("Raichu");
出力値
進化後: Raichu (Electric)
解答コード例
public class Pokemon {
// ポケモンの名前
private String name;
// ポケモンのタイプ
private String type;
// 名前を取得するメソッド
public String getName() {
return name;
}
// 名前を設定するメソッド
public void setName(String name) {
this.name = name;
}
// タイプを取得するメソッド
public String getType() {
return type;
}
// タイプを設定するメソッド
public void setType(String type) {
this.type = type;
}
// ポケモンの情報を表示するメソッド
public String getInfo() {
return name + " (" + type + ")";
}
// ポケモンを進化させるメソッド
// 引数で新しい名前を受け取り、名前を変更し、進化後の情報を表示する
public void evolve(String newName) {
this.name = newName; // 名前を新しい名前に変更
System.out.println("進化後: " + getInfo()); // 変更後の情報を出力
}
}
解説補足:
記事の構成上、Pokemonクラスは「基本版」「evolve追加版」「learnMoves追加版」「レベル追加版」など、段階的に書き換えています。
実際のプロジェクトでは、最後に 1 つのPokemonクラスに統合して使用してください(末尾に統合例を載せています)。
2. ポケモンクラスに、if文とfor文と配列を利用した処理を追加
Pokemon クラスの拡張
以下の仕様に従って、Pokemon クラスに learnMoves(String[] moves) メソッドを追加してください。
新規メソッド
-
learnMoves(String[] moves)- ポケモンが覚える技の一覧を表示します。
- 配列
movesに含まれる各技名を順番に出力します。 - 配列が
nullまたは空の場合は"覚える技がありません"と出力してください。
出力例
入力値
Pokemon p = new Pokemon();
p.setName("Pikachu");
String[] moves = {"Thunderbolt", "Quick Attack", "Iron Tail"};
p.learnMoves(moves);
出力値
Pikachu が覚える技:
- Thunderbolt
- Quick Attack
- Iron Tail
※元記事の出力例の 3 行目が - - Iron Tail となっていましたが、
実際のコードの動作に合わせて - Iron Tail に修正しています(仕様意図は同じです)。
解答コード例
public class Pokemon {
private String name;
private String type;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getInfo() {
return name + " (" + type + ")";
}
// 技を覚える処理。if文とfor文と配列の使い方を確認するメソッド
public void learnMoves(String[] moves) {
// 技が何も指定されていない場合
if (moves == null || moves.length == 0) {
System.out.println("覚える技がありません");
return;
}
// 技がある場合、それぞれを順番に表示
System.out.println(name + " が覚える技:");
for (String move : moves) {
System.out.println("- " + move); // 各技名を表示
}
}
}
3. ポケモンクラスから、ピカチュウクラスを継承
Pikachu クラスの作成
-
Pokemonクラスを継承し、名前を"Pikachu"、タイプを"Electric"に初期設定するコンストラクタを作成してください。
出力例
入力値
Pikachu pika = new Pikachu();
System.out.println(pika.getInfo());
出力値
Pikachu (Electric)
解答コード例
public class Pikachu extends Pokemon {
// Pikachu 固有のコンストラクタ。名前とタイプを自動設定
public Pikachu() {
setName("Pikachu"); // 名前を"Pikachu"に設定
setType("Electric"); // タイプを"Electric"に設定
}
}
4. ピカチュウクラスから、ライチュウクラスを継承
Raichu クラスの作成
-
Pikachuクラスを継承し、名前を"Raichu"に上書きするコンストラクタを作成してください。
出力例
入力値
Raichu r = new Raichu();
System.out.println(r.getInfo());
出力値
Raichu (Electric)
解答コード例
public class Raichu extends Pikachu {
// Raichu コンストラクタ。親クラス Pikachu のタイプを継承しつつ名前を変更
public Raichu() {
setName("Raichu"); // 名前を"Raichu"に設定(タイプはElectricのまま)
}
}
5. ポケモンクラスから、イーブイクラスを継承
Eevee クラスの作成
-
Pokemonクラスを継承し、名前を"Eevee"、タイプを"Normal"に設定するコンストラクタを作成してください。
出力例
入力値
Eevee e = new Eevee();
System.out.println(e.getInfo());
出力値
Eevee (Normal)
解答コード例
public class Eevee extends Pokemon {
// Eeveeのコンストラクタで初期設定を行う
public Eevee() {
setName("Eevee"); // 名前を"Eevee"に設定
setType("Normal"); // タイプを"Normal"に設定
}
}
6. ポケモンクラスから、ゼニガメクラスを継承
Squirtle クラスの作成
-
Pokemonクラスを継承し、名前を"Squirtle"、タイプを"Water"に設定するコンストラクタを作成してください。
出力例
入力値
Squirtle s = new Squirtle();
System.out.println(s.getInfo());
出力値
Squirtle (Water)
解答コード例
public class Squirtle extends Pokemon {
// Squirtleのコンストラクタで初期値を設定する
public Squirtle() {
setName("Squirtle"); // 名前を"Squirtle"に設定
setType("Water"); // タイプを"Water"に設定
}
}
7. ポケモンクラス自体をリファクタリングして機能追加
Pokemon クラスのリファクタリング
- 以下のフィールドとメソッドを追加してください。
フィールド追加
-
level(型: int): ポケモンのレベル(初期値は1)
メソッド追加
-
getLevel()/setLevel(int level) -
levelUp(): レベルを1上げて"Pikachuのレベルが2になった!"のように出力する
出力例
入力値
Pokemon p = new Pokemon();
p.setName("Pikachu");
p.setType("Electric");
p.setLevel(5);
p.levelUp();
System.out.println(p.getLevel());
出力値
Pikachuのレベルが6になった!
6
解答コード例
public class Pokemon {
private String name;
private String type;
private int level = 1; // レベルの初期値は1
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getInfo() {
return name + " (" + type + ")";
}
// レベルを取得する
public int getLevel() {
return level;
}
// レベルを設定する
public void setLevel(int level) {
this.level = level;
}
// レベルアップ処理を行う
public void levelUp() {
level += 1; // レベルを1上げる
System.out.println(name + "のレベルが" + level + "になった!");
}
}
注意:
このステップでPokemonクラスにlevelが追加されるため、
4. で定義したBattlePokemonのlevelと二重定義になる可能性があります。
最終的な設計としては、レベルを「全ポケモン共通」にしたい場合はPokemon側のlevelを使い、
BattlePokemon側のlevelフィールドは削除する、などの整理を行ってください。
8. 継承したクラスが、7. のリファクタリングでどのような影響を受けたか説明
影響内容の説明
ポイント
-
PokemonクラスにlevelフィールドとlevelUp()メソッドが追加されたことで、
すべてのサブクラス(Pikachu, Raichu, Eevee, Squirtle など) も自動的にレベルの管理ができるようになりました。 - 例えば、
Raichuクラスのインスタンスに対してsetLevel(10)やlevelUp()を使うことが可能になります。 - これにより、コードの再利用性が向上し、各進化ポケモンが共通の成長ロジックを持つことができます。
例
Raichu r = new Raichu();
r.setLevel(10);
r.levelUp(); // => Raichuのレベルが11になった!
メリットまとめ
- レベルの一括管理が基底クラスで可能に
- サブクラスは何も変更せずともレベル機能を自動的に継承
- メソッド追加時に影響範囲を最小限に抑えた設計ができる
おまけ: 最終版Pokemonクラスの統合例
記事中では学習のため段階的に Pokemon クラスを拡張していますが、
実際のプロジェクトでは、以下のように 1 つの Pokemon クラスにまとめて使うことができます。
public class Pokemon {
private String name;
private String type;
private int level = 1; // レベルの初期値は1
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getInfo() {
return name + " (" + type + ")";
}
// ポケモンを進化させるメソッド
public void evolve(String newName) {
this.name = newName;
System.out.println("進化後: " + getInfo());
}
// 技を覚える処理。if文とfor文と配列の使い方を確認するメソッド
public void learnMoves(String[] moves) {
if (moves == null || moves.length == 0) {
System.out.println("覚える技がありません");
return;
}
System.out.println(name + " が覚える技:");
for (String move : moves) {
System.out.println("- " + move);
}
}
// レベルを取得する
public int getLevel() {
return level;
}
// レベルを設定する
public void setLevel(int level) {
this.level = level;
}
// レベルアップ処理を行う
public void levelUp() {
level += 1;
System.out.println(name + "のレベルが" + level + "になった!");
}
}