📚 目次
- 🔹 第1章 ポケモン図鑑を作ろう!クラスの設計図
- 🔹 1.1 オブジェクトとは
- 🔹 1.2 クラスを作る
- 🔹 1.3 まとめとテスト
- 🔹 第2章 モンスターボールからGET!インスタンスの作り方と使い方
- 🔹 2.1 インスタンスを作る
- 🔹 2.2 ゲッターとセッターの使い方
- 🔹 2.3 メソッドを追加する
- 🔹 2.4 まとめとテスト
- 🔹 第3章 ポケモンのひみつを守れ!クラスの仕組み
- 🔹 3.1 他のクラスからのアクセスを制限する
- 🔹 3.2 メンバの仕組み
- 🔹 3.3 コンストラクタの仕組み
- 🔹 3.4 まとめとテスト
- 🔹 第4章 ポケモンを指し示せ!インスタンスと参照の秘密
- 🔹 4.1 参照とは
- 🔹 4.2 参照を意識する
- 🔹 4.3 完全にイミュータブルなクラスを作ろう!
- 🔹 4.4 参照型
- 🔹 4.5 まとめとテスト
- 🔹 第5章 オリジナルポケモンを設計せよ!オブジェクト・モデリング
- 🔹 5.1 何かの機能を実現するクラス
- 🔹 5.2 record
- 🔹 5.3 まとめとテスト
- 🔹 第6章 進化の秘密を解明!継承という血筋
- 🔹 6.1 クラス図
- 🔹 6.2 継承
- 🔹 6.3 継承の規則
- 🔹 6.4 まとめとテスト
- 🔹 第7章 ポケモン家系の謎!継承関係を究める
- 🔹 7.1 継承ツリー
- 🔹 7.2 コンストラクタの連鎖
- 🔹 7.3 複数のクラスを1つのファイルにする
- 🔹 7.4 protected修飾子
- 🔹 7.5 まとめとテスト
- 🔹 第8章 ポケモンの変身術!参照の自動型変換
- 🔹 8.1 参照の自動型変換
- 🔹 8.2 アップキャストとダウンキャスト
- 🔹 8.3 instanceof演算子
- 🔹 8.4 switchによる型の判定
- 🔹 8.5 まとめとテスト
- 🔹 第9章 一つの技で多様な効果!ポリモーフィズム(多態性)
- 🔹 9.1 オーバーロード
- 🔹 9.2 オーバーライド
- 🔹 9.3 ポリモーフィズム(多態性)
- 🔹 9.4 まとめとテスト
- 🔹 第10章 幻のポケモンの謎!抽象クラスの世界
- 🔹 10.1 抽象クラスとは
- 🔹 10.2 抽象クラスを継承する
- 🔹 10.3 抽象クラスのクラス図
- 🔹 10.4 まとめとテスト
- 🔹 第11章 ポケモンのタイプと能力!インタフェースの力
- 🔹 11.1 インタフェースとは
- 🔹 11.2 インタフェース型への型変換
- 🔹 11.3 インタフェースによるポリモーフィズム
- 🔹 11.4 インタフェースの継承
- 🔹 11.5 まとめとテスト
🧩 第1章 ポケモン図鑑を作ろう!クラスの設計図
🎯 1.1 オブジェクトとは
🌟 ポケモンもオブジェクト?実は身近なオブジェクト指向の世界
ポケモンの世界では、ピカチュウやヒトカゲなど、すべてのポケモンが「オブジェクト」です。
現実世界で例えるなら、「自転車」や「スマートフォン」もオブジェクトです。
オブジェクトには2つの要素があります:
- 🧬 属性(フィールド):たとえばピカチュウの「名前」「タイプ」「レベル」など
- 🛠 操作(メソッド):ピカチュウが使う「10まんボルト」や「なきごえ」などの技
🧠 ピカチュウのステータスを集めよう!データをまとめるオブジェクトの魔法
Javaでは、オブジェクトとは「データ(属性)」と「ふるまい(操作)」をひとまとめにしたものです。
例えばピカチュウなら、以下のように表現できます。
// ピカチュウというオブジェクトの一例(擬似コード)
名前: "ピカチュウ"
タイプ: "でんき"
レベル: 15
使える技: 10まんボルト, なきごえ
🏗 1.2 クラスを作る
📘 図鑑に載せる前に!クラスという設計図の大切さ
クラスとは、「オブジェクトの設計図」です。
たとえば「ポケモン」というクラスがあれば、それをもとにピカチュウ、ヒトカゲなど、色々なポケモンのオブジェクトを作れます。
🧠 クラスを使うメリットってなに?
ポケモンを「クラス」で定義することで、何が便利になるのでしょうか?
以下の表にまとめてみました:
項目 | 配列や個別変数だけで書く場合 | クラスを使う場合のメリット |
---|---|---|
情報のまとまり | name, type, levelを別々に管理 | 1つのオブジェクトでまとめて管理できる |
拡張性 | 新しい項目を追加するたびに管理が複雑になる | クラス内に変数やメソッドを追加するだけ |
再利用性 | 同じ処理を何度も書く必要がある | メソッドで共通処理をまとめて再利用できる |
読みやすさ | 情報のつながりが見えにくい | データとふるまいがセットで直感的 |
保守性 | バグが見つかりにくい | クラス内にロジックが集中するので修正しやすい |
🛠 クラスの定義例(Java)
// ポケモンクラスの定義
public class Pokemon {
String name; // ポケモンの名前(例:ピカチュウ)
String type; // タイプ(例:でんき)
int level; // レベル(整数で管理)
// ポケモンが自己紹介するメソッド
public void introduce() {
System.out.println("こんにちは!私は" + name + "、タイプは" + type + "、レベルは" + level + "です!");
}
}
📝 このクラスでは、
-
name
:ポケモンの名前を文字列型で管理します。 -
type
:ポケモンのタイプ(例:「ほのお」や「くさ」)を文字列型で管理します。 -
level
:レベルを整数(int型)で管理します。 -
introduce()
:このポケモンの自己紹介を表示するメソッドです。
🧪 1.3 まとめとテスト
✅ ポケモンクラスのまとめ
要素 | 内容 |
---|---|
クラス | 設計図(ポケモンの共通情報) |
オブジェクト | 実際に生まれたピカチュウやヒトカゲ |
属性 | 名前・タイプ・レベル |
メソッド | 自己紹介などのふるまい |
📝 練習問題
- 自分だけのポケモンを考えて、
Pokemon
クラスで表現してみましょう。 -
introduce()
メソッドの中で「使える技」も紹介できるように拡張してみよう。
🔍 解答例(コメント付き)
public class Pokemon { // ポケモンを表すクラス(設計図)
String name; // ポケモンの名前を保持する文字列型の変数
String type; // ポケモンのタイプ(例:でんき、みず等)を保持する変数
int level; // ポケモンのレベルを保持する整数型の変数
String move; // ポケモンが使える技を文字列で保持する変数
public void introduce() { // 自己紹介を行うメソッド
// 名前、タイプ、レベルを出力
System.out.println("こんにちは!私は" + name + "、タイプは" + type + "、レベルは" + level + "です!");
// 技の紹介を出力
System.out.println("わざは「" + move + "」が使えるよ!");
}
}
public class Main {
public static void main(String[] args) {
Pokemon pika = new Pokemon(); // Pokemon型の新しいインスタンスを作成し、変数pikaに代入
pika.name = "ピカチュウ"; // ピカチュウという名前を設定(文字列)
pika.type = "でんき"; // タイプを「でんき」に設定
pika.level = 15; // レベルを整数15に設定
pika.move = "10まんボルト"; // 技を「10まんボルト」に設定
pika.introduce(); // introduceメソッドを呼び出して自己紹介を表示
}
}
🧩 このように、クラスを使うとポケモン1匹分の情報と動作をセットでまとめて管理できるため、とても便利です。
🧩 このプログラムでは、Pokemon
クラスを使ってピカチュウの情報を登録し、自己紹介させています。
🎯 第2章 モンスターボールからGET!インスタンスの作り方と使い方
🧱 2.1 インスタンスを作る
🥚 ポケモンを召喚せよ!new演算子とコンストラクタの呪文
Javaでは、「new」キーワードを使うことで、クラスからオブジェクト(インスタンス)を生み出します。
これはまるでモンスターボールからポケモンを出すようなものです!
Pokemon pika = new Pokemon();
-
Pokemon
:設計図(クラス)の名前 -
pika
:作られたピカチュウのインスタンス(オブジェクト) -
new Pokemon()
:新しいポケモンを作る魔法の呪文(コンストラクタの呼び出し)
🎒 捕まえたポケモンをボックスに預けよう!変数という箱の秘密
pika
という変数は、モンスターボールのような箱で、ポケモンオブジェクトを入れておくためのものです。
Pokemon pika = new Pokemon();
📝 これは「Pokemon型の変数pikaを定義し、newで生成したオブジェクトを代入している」処理です。
🔓 2.2 ゲッターとセッターの使い方
🔍 「きみのHPはいくつ?」ゲッターでステータスを確認
ゲッターとは、ポケモンの情報(フィールド)を取り出すためのメソッドです。
public String getName() {
return name; // 文字列型変数nameの値を返す
}
💪 「レベルアップ!」セッターでポケモンを強化する
セッターは、ポケモンの情報を変更したいときに使います。
public void setLevel(int lvl) {
level = lvl; // int型変数lvlの値をint型変数levelに代入する
}
✨ ゲッター・セッター付きのPokemonクラス
public class Pokemon {
private String name;
private String type;
private int level;
private String move;
public void setName(String name) { this.name = name; }
public void setType(String type) { this.type = type; }
public void setLevel(int level) { this.level = level; }
public void setMove(String move) { this.move = move; }
public String getName() { return name; }
public String getType() { return type; }
public int getLevel() { return level; }
public String getMove() { return move; }
}
🛠 2.3 メソッドを追加する
📢 「ピカチュウ、自己紹介して!」toStringメソッドの秘密
toString()
は、オブジェクトの内容を文字列で表示する特別なメソッドです。
@Override
public String toString() {
return "ポケモン:" + name + " / タイプ:" + type + " / レベル:" + level + " / わざ:" + move;
}
⚡ 「10まんボルト」実装大作戦!技を使うメソッドを作ろう
public void useMove() {
System.out.println(name + "の" + move + "!こうかはばつぐんだ!");
}
📝 このメソッドは、ポケモンがわざを使ったときの表示を再現します。
🎯 2.4 まとめとテスト
✅ インスタンス操作のポイント
用語 | 説明 |
---|---|
インスタンス | new演算子で作成したオブジェクト |
ゲッター | フィールドの値を取得するメソッド |
セッター | フィールドの値を設定するメソッド |
toString | オブジェクトの状態を文字列に変換 |
任意メソッド | オリジナル技や動作を実装 |
🧪 動作確認!最終サンプルコード
public class Pokemon {
private String name;
private String type;
private int level;
private String move;
public void setName(String name) { this.name = name; }
public void setType(String type) { this.type = type; }
public void setLevel(int level) { this.level = level; }
public void setMove(String move) { this.move = move; }
public String getName() { return name; }
public String getType() { return type; }
public int getLevel() { return level; }
public String getMove() { return move; }
public void useMove() {
System.out.println(name + "の" + move + "!こうかはばつぐんだ!");
}
@Override
public String toString() {
return "ポケモン:" + name + " / タイプ:" + type + " / レベル:" + level + " / わざ:" + move;
}
}
public class Main {
public static void main(String[] args) {
Pokemon pika = new Pokemon(); // Pokemon型オブジェクトpikaを生成
pika.setName("ピカチュウ"); // 名前を設定
pika.setType("でんき"); // タイプを設定
pika.setLevel(25); // レベルを設定
pika.setMove("10まんボルト"); // わざを設定
System.out.println(pika); // オブジェクト内容を出力
pika.useMove(); // わざを使う
}
}
🧩 このサンプルで、クラス → インスタンス生成 → 値の設定 → メソッドの実行という一連の流れを体験できます!
🛡 第3章 ポケモンのひみつを守れ!クラスの仕組み
🔐 3.1 他のクラスからのアクセスを制限する
🧳 「そのHPは見せられない!」privateとpublicの境界線
ポケモンの「HP」や「覚えている技」は、ほかのトレーナーから勝手に見られたら困るかもしれませんよね?
Javaでは、「アクセス修飾子」を使って、クラスの中の情報を守ることができます。
public class Pokemon {
private int hp; // 他のクラスからは直接見えないようにする(非公開)
public int getHp() {
return hp; // 値を返す(公開)
}
public void setHp(int hp) {
this.hp = hp; // 外部から値を設定する方法を用意(公開)
}
}
📝 private
は非公開、public
は公開を意味します。
🧩 グレーゾーンの属性!修飾子なしの不思議な世界
アクセス修飾子を何も書かなかった場合、同じパッケージの中からはアクセスできます。
これを「デフォルト(パッケージ)アクセス」と呼びます。
✨️独自仕様:Javaでは明示的にアクセス範囲を決めることで安全性を保つのが基本です。
🛡 秘密のステータスを保護せよ!カプセル化の真髄
カプセル化とは、「データをクラスの中に閉じ込めて、外部からの不正なアクセスを防ぐこと」です。
ポケモンでいえば、「ステータス画面はトレーナーだけが操作できる」状態ですね!
⚙️ 3.2 メンバの仕組み
⚡ 「全ポケモン共通の特性」スタティックメンバの超パワー
すべてのポケモンに共通する特性、たとえば「ポケモンの世界共通の最大レベル」はstatic
で表現できます。
public class Pokemon {
public static final int MAX_LEVEL = 100; // 全ポケモン共通の最大レベル
}
📝 static
はクラス全体で共通の変数やメソッドを意味します。
🧬 「このピカチュウだけの特性」インスタンスメンバの個性
一方、各ポケモンが持つ「レベル」や「名前」などはインスタンスメンバです。
public class Pokemon {
private int level; // このポケモンだけが持つ個別の値
}
⚠️ スタティックとインスタンス、共存できるの?
もちろんできますが、違いをしっかり意識することが大切です。
public class Pokemon {
public static final int MAX_LEVEL = 100;
private int level;
public boolean isMaxLevel() {
return level == MAX_LEVEL; // クラス変数との比較
}
}
🧱 3.3 コンストラクタの仕組み
🌀 同じ名前で違う生まれ方?オーバーロードの魔法
Javaでは、**コンストラクタを複数持たせる(オーバーロード)**ことができます。
これは、いろいろな条件でポケモンを生み出す技のようなものです。
public Pokemon() {
this.name = "ピカチュウ"; // デフォルトの名前を設定
}
public Pokemon(String name) {
this.name = name; // 引数で指定された名前を使う
}
🌈 「色違いポケモン」も作れる!コンストラクタを増やす技
public Pokemon(String name, int level, String type) {
this.name = name; // 名前をセット
this.level = level; // レベルをセット
this.type = type; // タイプをセット
}
🔁 「this」で簡単!コンストラクタの連携プレイ
public Pokemon(String name, int level) {
this(name, level, "ノーマル"); // 他のコンストラクタを呼び出す
}
📝 this()
は「同じクラス内の別のコンストラクタを呼び出す」特別な書き方です。
🧊 何も指定しなくても生まれるポケモン?デフォルトコンストラクタの謎
コンストラクタを定義しないと、Javaは自動で**デフォルトコンストラクタ(引数なし)**を用意してくれます。
しかし、他にコンストラクタがあると自動生成されません。注意しましょう!
🧪 3.4 まとめとテスト
📘 第3章まとめ:カプセル化とメンバ管理の極意
項目 | 内容 |
---|---|
アクセス修飾子 | データの見せる/見せないを設定する方法 |
private | 他のクラスからは見えない |
public | どこからでも使える |
static | 全ポケモン共通の性質(例:MAX_LEVEL) |
コンストラクタ | ポケモンを生み出すための特別なメソッド |
this | 自分自身を指す/他のコンストラクタを呼び出す |
🎮 テストコード:ここまでの総まとめ
public class Pokemon {
private String name;
private String type;
private int level;
public static final int MAX_LEVEL = 100;
public Pokemon() {
this("ピカチュウ", 5, "でんき");
}
public Pokemon(String name, int level, String type) {
this.name = name;
this.level = level;
this.type = type;
}
public String getName() { return name; }
public String getType() { return type; }
public int getLevel() { return level; }
public void setLevel(int level) { this.level = level; }
public boolean isMaxLevel() {
return level == MAX_LEVEL;
}
public void introduce() {
System.out.println("私は" + name + "!タイプ:" + type + "、レベル:" + level);
}
}
public class Main {
public static void main(String[] args) {
Pokemon pika = new Pokemon(); // デフォルトのピカチュウを生成
pika.introduce(); // 自己紹介
Pokemon eve = new Pokemon("イーブイ", 10, "ノーマル");
eve.introduce();
System.out.println("イーブイは最大レベル?:" + eve.isMaxLevel());
}
}
🧩 このサンプルでは、カプセル化・static・コンストラクタオーバーロードをすべて体験できます!
🧭 第4章 ポケモンを指し示せ!インスタンスと参照の秘密
🎯 4.1 参照とは
🎈 モンスターボールとポケモンの関係?参照の不思議な役割
ポケモンの世界では、「モンスターボール」はポケモンをしまっておくケースのようなもの。
Javaでは、このモンスターボールが「参照(Reference)」にあたります。
Pokemon pika1 = new Pokemon(); // ポケモンを1体作る
Pokemon pika2 = pika1; // pika1のポケモンを、pika2にも渡す
📝 pika2
はpika1
と同じポケモンを指し示しているだけで、別のポケモンではありません。
👀 4.2 参照を意識する
🧪 「コピーしたはずなのに同じポケモン!?」変数間の代入の真実
pika2.setLevel(50); // pika2でレベルを変更すると…
System.out.println(pika1.getLevel()); // pika1でも反映されている!
📌 オブジェクトは本体ではなく「場所(アドレス)」を変数が指していると理解しましょう。
✨️独自仕様:「ポケモンの個体値」を考慮した場合の注意
もし「まったく同じ見た目だけど別の個体のピカチュウ」が必要な場合は、コピーを作る仕組みが必要になります。
🧊 4.3 完全にイミュータブルなクラスを作ろう!
🧼 「誰も変えられない伝説のポケモン」完全イミュータブルの実装法
public final class Pokemon {
private final String name;
private final String type;
private final int level;
public Pokemon(String name, String type, int level) {
this.name = name;
this.type = type;
this.level = level;
}
public String getName() { return name; }
public String getType() { return type; }
public int getLevel() { return level; }
}
🛡 このクラスでは、すべてのフィールドがfinal
で、一度決めたら二度と変えられません。
🧬 4.4 参照型
🧪 「プリミティブ型との違いは?」Java言語の型システム解剖
型の種類 | 例 | 特徴 |
---|---|---|
プリミティブ型 |
int , double , boolean
|
値そのものを扱う |
参照型 |
String , Pokemon , List
|
オブジェクトの**場所(参照)**を扱う |
⚠️ 「空っぽのモンスターボール?」nullの正体と危険性
Pokemon pika = null; // まだ何も入っていないモンスターボール
pika.introduce(); // ← これをするとエラー!(NullPointerException)
🚨 null
は「まだ中身がない」状態なので、呼び出そうとするとクラッシュします!
🧪 4.5 まとめとテスト
🧾 第4章まとめ:参照とイミュータブルの理解
キーワード | 内容 |
---|---|
参照 | オブジェクトの場所(アドレス)を指す |
同じ参照 | 変数を代入すると同じオブジェクトを参照する |
null | 何も入っていない状態。アクセスするとエラー |
イミュータブル | 値が一切変わらないようにする設計 |
🧪 総合テストコード
public final class Pokemon {
private final String name;
private final String type;
private final int level;
public Pokemon(String name, String type, int level) {
this.name = name;
this.type = type;
this.level = level;
}
public String getName() { return name; }
public String getType() { return type; }
public int getLevel() { return level; }
public void introduce() {
System.out.println("私は" + name + "!タイプ:" + type + "、レベル:" + level);
}
}
public class Main {
public static void main(String[] args) {
Pokemon pika1 = new Pokemon("ピカチュウ", "でんき", 25);
Pokemon pika2 = pika1; // 同じポケモンを参照
pika1.introduce();
pika2.introduce(); // 同じ内容が出力される
// nullポケモンの例(コメントアウトしないと実行時エラー)
// Pokemon empty = null;
// empty.introduce(); // NullPointerException
}
}
🔍 参照とは何か、nullとはどう危険なのかをこのコードでしっかり体験しよう!
🧪 第5章 オリジナルポケモンを設計せよ!オブジェクト・モデリング
🧱 5.1 何かの機能を実現するクラス
📝 「どんなポケモンを作る?」処理の全体像を考えよう
ポケモンゲームでは、名前、タイプ、レベル、覚えている技など、さまざまな情報が必要です。
これをクラスでどう表現するかを考えるのが「オブジェクト・モデリング」です。
🧮 「特性と技を決めよう」クラス定義の設計図を描く
public class Pokemon {
private String name; // ポケモンの名前(例:フシギダネ)
private String type; // ポケモンのタイプ(例:くさ)
private int level; // レベル(整数で表現)
private String[] moves; // 覚えている技を配列で管理
public Pokemon(String name, String type, int level, String[] moves) {
this.name = name;
this.type = type;
this.level = level;
this.moves = moves;
}
public void introduce() {
System.out.println("名前:" + name + " / タイプ:" + type + " / レベル:" + level);
System.out.println("覚えている技:");
for (String move : moves) {
System.out.println("- " + move);
}
}
}
📝 このクラスは、基本情報と技の一覧を保持し、自己紹介メソッドで出力するようになっています。
🚀 「本当にこれでいい?」最終仕様の見直しポイント
- 技は何個まで? → 今回は配列で自由に対応
- レベルの上限は? → static final で固定可能
- 複数のタイプはどうする? → ✨️独自仕様:今回は1タイプのみに限定
⚙️ 「いざ実装!」設計図からコードへの変換テクニック
String[] fushiMoves = {"たいあたり", "つるのムチ", "どくのこな"};
Pokemon fushigidane = new Pokemon("フシギダネ", "くさ", 10, fushiMoves);
fushigidane.introduce();
📝 String[]
を使って複数の技をまとめて管理し、クラスに渡しています。
📦 5.2 record
🆕 「Java 16の新機能!」recordって何者?
Java 16以降では、簡単にデータクラスを定義できる構文としてrecord
が導入されました。
public record SimplePokemon(String name, String type, int level) {}
✨️「簡単ポケモン図鑑エントリ」recordの定義と便利機能
recordは、
コンストラクタ
getter
toString()
-
equals()
などを自動で作ってくれるため、コードが短くなります。
SimplePokemon zenigame = new SimplePokemon("ゼニガメ", "みず", 8);
System.out.println(zenigame.name()); // getterのように値が取れる
System.out.println(zenigame); // 自動でtoStringが使われる
🧠 「もっと強化したい!」recordに機能を追加する方法
recordにもメソッドを追加できます。
public record SimplePokemon(String name, String type, int level) {
public boolean isStarter() {
return level <= 10;
}
}
🔒 「絶対に変わらない伝説のポケモン」完全イミュータブルrecord
recordは**すべてのフィールドがfinal(変更不可)**です。
まさに「ミュウツー」や「ルギア」のような、伝説ポケモンにふさわしい設計です。
🪄 「3行でポケモン作成!」超簡単record活用術
SimplePokemon hitokage = new SimplePokemon("ヒトカゲ", "ほのお", 5);
System.out.println("スタメン候補:" + hitokage.name());
🎯 5.3 まとめとテスト
✅ モデリングとrecordのポイント
概念 | 説明 |
---|---|
モデリング | 現実世界(ポケモン)をプログラムで再現する設計 |
フィールド | ポケモンの名前、タイプ、技などの情報 |
メソッド | 自己紹介や技の実行などの動作 |
record | 簡易データクラス(不変・軽量) |
イミュータブル | 値が変わらない安全なオブジェクト |
💻 総合サンプルコード
public class Pokemon {
private String name;
private String type;
private int level;
private String[] moves;
public Pokemon(String name, String type, int level, String[] moves) {
this.name = name;
this.type = type;
this.level = level;
this.moves = moves;
}
public void introduce() {
System.out.println("名前:" + name + " / タイプ:" + type + " / レベル:" + level);
System.out.println("覚えている技:");
for (String move : moves) {
System.out.println("- " + move);
}
}
}
public record SimplePokemon(String name, String type, int level) {
public boolean isStarter() {
return level <= 10;
}
}
public class Main {
public static void main(String[] args) {
String[] moves = {"たいあたり", "つるのムチ", "どくのこな"};
Pokemon bulbasaur = new Pokemon("フシギダネ", "くさ", 10, moves);
bulbasaur.introduce();
SimplePokemon charmander = new SimplePokemon("ヒトカゲ", "ほのお", 5);
System.out.println("スタメン候補:" + charmander.name());
System.out.println("スターター?:" + charmander.isStarter());
}
}
🧩 このコードでは、クラスによるモデルとrecordによる軽量データ定義の両方が体験できます!
🧬 第6章 進化の秘密を解明!継承という血筋
📊 6.1 クラス図
📚 「ポケモン図鑑の裏側」クラス図の読み解き方
Javaの継承は、図鑑の進化ツリーのようなものです。
例えば「ピチュー → ピカチュウ → ライチュウ」の関係をクラス図で表すと、以下のようになります。
Pokemon(親クラス)
└─ Pikachu(子クラス)
└─ Raichu(孫クラス)
📝 このように、「共通する情報」は親クラスに、「進化して追加される情報」は子クラスに記述します。
✨️独自仕様:クラス図ツールがない場合はテキストで描いてもOK!
🧪 6.2 継承
👪 「ピチューからピカチュウへ」継承でクラスを拡張する方法
public class Pokemon {
String name;
String type;
public void introduce() {
System.out.println("私は" + name + "タイプは" + type + "です!");
}
}
public class Pikachu extends Pokemon {
int level;
public void thunderbolt() {
System.out.println(name + "の10まんボルト!");
}
}
📝 Pikachu
クラスはPokemon
クラスを継承して、level
とthunderbolt
という追加要素を持たせています。
🐣 「卵からの孵化」インスタンス初期化の順序と仕組み
Javaでは、親クラスのコンストラクタが先に呼ばれ、次に子クラスのコンストラクタが呼ばれます。
public class Pokemon {
public Pokemon() {
System.out.println("ポケモンが誕生!");
}
}
public class Pikachu extends Pokemon {
public Pikachu() {
System.out.println("ピカチュウが生まれた!");
}
}
結果は以下の順番で表示されます:
ポケモンが誕生!
ピカチュウが生まれた!
🚀 「進化するとできること」継承の効果を実感しよう
Pikachu pika = new Pikachu();
pika.name = "ピカチュウ";
pika.type = "でんき";
pika.level = 15;
pika.introduce(); // 親クラスのメソッド
pika.thunderbolt(); // 自分のメソッド
📜 6.3 継承の規則
🧠 「〇〇は〇〇である」Is-a関係の重要性
「ピカチュウはポケモンである」このようなIs-aの関係が成立するのが継承です。
逆に「ポケモンはピカチュウである」は成立しないため、逆の継承はできません。
🚫 「伝説のポケモンは複製できない」継承できないクラスの秘密
public final class Mewtwo extends Pokemon {
// このクラスは継承できません(final)
}
📝 final
をつけると、そのクラスはこれ以上進化(継承)されないようにできます。
🔒 「封印された特性」シールクラスの不思議な力
✨️独自仕様:**sealed class(Java 17〜)**を使うと、継承できるクラスを限定できます。
public sealed class Pokemon permits Pikachu, Eevee {}
この場合、Pokemon
を継承できるのはPikachu
とEevee
だけです。
🧙 「一子相伝の技」継承できないメンバの特徴
-
private
なフィールドやメソッドは子クラスでは使えません。 -
final
なメソッドはオーバーライドできません。
🎯 6.4 まとめとテスト
📘 継承のまとめ
概念 | 説明 |
---|---|
継承(extends) | クラスの機能を引き継ぐ |
親クラス | 基本の共通機能を持つクラス |
子クラス | 特定の追加機能を持つクラス |
Is-a関係 | ○○は××である、という関係 |
final | それ以上継承できない |
sealed(Java17) | 継承先を限定する(✨️独自仕様) |
💻 総合サンプルコード
public class Pokemon {
String name;
String type;
public void introduce() {
System.out.println("私は" + name + "、タイプは" + type + "です!");
}
}
public class Pikachu extends Pokemon {
int level;
public Pikachu(String name, int level) {
this.name = name;
this.type = "でんき";
this.level = level;
}
public void thunderbolt() {
System.out.println(name + "の10まんボルト! こうかはばつぐんだ!");
}
}
public class Main {
public static void main(String[] args) {
Pikachu pika = new Pikachu("ピカチュウ", 20); // Pikachuクラスのインスタンス作成
pika.introduce(); // 親クラスのメソッドを呼び出す
pika.thunderbolt(); // 子クラス独自のメソッドを呼び出す
}
}
🧩 このサンプルで、継承・コンストラクタ・オーバーライド・親子関係すべてを実践しよう!
🧬 第7章 ポケモン家系の謎!継承関係を究める
🌳 7.1 継承ツリー
🧭 「ポケモン進化の樹形図」継承ツリーの全体像
ポケモンには家系図のような進化の系統があります。
Javaでも「継承ツリー」として、親子関係を構築できます。
例)ニャース → ニャイキング(✨️独自仕様:地方進化)
Pokemon
├── Meowth
│ └── Perrserker
└── Eevee
├── Vaporeon
├── Jolteon
└── Flareon
🧬 「全てのポケモンのご先祖様」Objectクラスの秘密
Javaのすべてのクラスは、暗黙的に Object
クラスを継承しています。
public class Pikachu {
// 実は Object クラスの toString() や equals() などが使える
}
📝 これにより、どのクラスにも標準機能が備わっているのです。
🔗 7.2 コンストラクタの連鎖
👶 「親から子へ、受け継がれる初期化」コンストラクタの連鎖の仕組み
親クラスと子クラスのコンストラクタは、順番に呼ばれる必要があります。
public class Pokemon {
public Pokemon(String name) {
System.out.println(name + " が生まれた!");
}
}
public class Eevee extends Pokemon {
public Eevee() {
super("イーブイ"); // 親クラスのコンストラクタを呼び出す
System.out.println("イーブイが準備完了!");
}
}
出力結果:
イーブイ が生まれた!
イーブイが準備完了!
❓ 「書かなくても呼ばれる?」super()省略時の挙動
引数なしのコンストラクタが親クラスに存在する場合、super()
の記述がなくても呼び出されます。
ただし、引数ありのコンストラクタしかないときは、super()を明示する必要あり!
📁 7.3 複数のクラスを1つのファイルにする
📄 「進化前と進化後を一緒に!」複数クラス定義のテクニック
public class Pokemon {
String name;
public void greet() {
System.out.println("やあ、" + name + "だよ!");
}
}
class Pikachu extends Pokemon {
public Pikachu() {
name = "ピカチュウ";
}
}
📝 ファイル名がPokemon.java
なら、public
がつくクラスは1つだけ。残りはpublic
を付けないことで共存可能です。
🛡 7.4 protected修飾子
🏠 「家族だけに見せる特性」protectedの特殊な力
public class Pokemon {
protected String name; // 自分と子クラス、同じパッケージ内のクラスからアクセスOK
}
⚠️ 「使い方を間違えると危険!」protected利用時の注意点
- 外部からアクセスできないとは限らない
- パッケージをまたぐと制限される
🌐 「public、private、protected、無印」アクセス修飾子の使い分け
修飾子 | 同じクラス内 | 同じパッケージ内 | 子クラス | 外部クラス |
---|---|---|---|---|
public | ○ | ○ | ○ | ○ |
protected | ○ | ○ | ○ | ×(異パッケージ) |
(なし) | ○ | ○ | × | × |
private | ○ | × | × | × |
🎯 7.5 まとめとテスト
🧾 第7章まとめ:Javaの家系図を完全理解!
概念 | 内容 |
---|---|
継承ツリー | クラス間の親子関係を構造的に表現 |
Objectクラス | すべてのクラスのご先祖さま |
super() | 親クラスのコンストラクタ呼び出し |
protected | パッケージと子クラスから見える属性 |
💻 総合サンプルコード
public class Pokemon {
protected String name;
public Pokemon(String name) {
this.name = name;
System.out.println(name + " が生まれた!");
}
public void greet() {
System.out.println("こんにちは!私は " + name + " です!");
}
}
class Pikachu extends Pokemon {
public Pikachu() {
super("ピカチュウ"); // 親クラスのコンストラクタ呼び出し
System.out.println("ピカチュウの準備完了!");
}
public void thunderbolt() {
System.out.println(name + " の 10まんボルト!");
}
}
public class Main {
public static void main(String[] args) {
Pikachu pika = new Pikachu();
pika.greet(); // 親クラスのメソッド
pika.thunderbolt(); // 子クラス独自の技
}
}
🎉 この章では、継承の構造・protected・クラスの共存と生成順までマスターできます!
🌀 第8章 ポケモンの変身術!参照の自動型変換
🪄 8.1 参照の自動型変換
🔁 「メタモンの変身」参照の自動型変換とは?
Javaでは、子クラスのオブジェクトを親クラスの型として扱うことができます。
これは、まるでメタモンが他のポケモンに変身して、他のポケモンとして行動しているようなイメージです!
Pokemon pika = new Pikachu("ピカチュウ", 20);
pika.introduce(); // 親クラスのメソッドは使える
📝 子クラスPikachu
のインスタンスが、親クラスPokemon
型の変数に代入されている。
🧱 8.2 アップキャストとダウンキャスト
⬆️ 「ピカチュウをポケモンとして扱う」アップキャスト
アップキャストとは、子クラス → 親クラス への変換です。(自動で行われます)
Pokemon poke = new Pikachu("ピカチュウ", 20);
⬇️ 「ポケモンの正体はピカチュウだった!」ダウンキャスト
ダウンキャストとは、親クラス → 子クラスへの変換です。
こちらは明示的にキャストが必要です。
Pikachu pika = (Pikachu) poke; // 明示的なキャスト
pika.thunderbolt(); // 子クラス独自のメソッドが使える!
⚠️ もしpokeがPikachu
以外だった場合、ClassCastException
というエラーになります!
🔍 8.3 instanceof演算子
🧪 「それってほんとにピカチュウ?」instanceofで正体を見破る方法
if (poke instanceof Pikachu) {
Pikachu pika = (Pikachu) poke; // 安全にキャストできる!
pika.thunderbolt();
}
📝 instanceof
は「このインスタンスはこの型か?」を確認できる便利な道具です。
🧠 8.4 switchによる型の判定
🌀 「タイプによって技が変わる」switch文とswitch式の威力(Java 14〜)
✨️独自仕様:Java 14以降で使える「型のパターンマッチング付きswitch」
switch (poke) {
case Pikachu p -> p.thunderbolt();
case Eevee e -> e.adapt();
default -> System.out.println("未知のポケモン!");
}
📝 switch文でもinstanceofとキャストを同時に行うことができるようになりました。
🎯 8.5 まとめとテスト
📘 変身の極意:まとめ
用語 | 説明 |
---|---|
アップキャスト | 子 → 親(自動) |
ダウンキャスト | 親 → 子(明示) |
instanceof | 型を安全に確認 |
switch式 | 型分岐を簡単に表現(Java 14以降) |
💻 総合サンプルコード
public class Pokemon {
protected String name;
public Pokemon(String name) {
this.name = name;
}
public void introduce() {
System.out.println("私は " + name + " です!");
}
}
class Pikachu extends Pokemon {
private int level;
public Pikachu(String name, int level) {
super(name);
this.level = level;
}
public void thunderbolt() {
System.out.println(name + " の 10まんボルト! レベル:" + level);
}
}
class Eevee extends Pokemon {
public Eevee(String name) {
super(name);
}
public void adapt() {
System.out.println(name + " はいろんなタイプに進化できる!");
}
}
public class Main {
public static void main(String[] args) {
Pokemon poke1 = new Pikachu("ピカチュウ", 25); // アップキャスト
Pokemon poke2 = new Eevee("イーブイ");
if (poke1 instanceof Pikachu) {
Pikachu pika = (Pikachu) poke1; // ダウンキャスト
pika.thunderbolt();
}
switch (poke2) {
case Pikachu p -> p.thunderbolt();
case Eevee e -> e.adapt();
default -> System.out.println("未知のポケモン");
}
}
}
🧩 これでポケモンの正体を見抜き、適切な技を使えるようになろう!
🎭 第9章 一つの技で多様な効果!ポリモーフィズム(多態性)
💡 9.1 オーバーロード
🧠 「同じ技の名前で別の効果」オーバーロードの仕組み
Javaでは、同じメソッド名で引数の数や型が違えば別のメソッドとして扱える、これがオーバーロードです。
まるで「たいあたり(通常)」と「たいあたり(ダブルバトル)」のような違い!
public void attack(String move) {
System.out.println("「" + move + "」を使った!");
}
public void attack(String move, int times) {
System.out.println("「" + move + "」を" + times + "回連続で使った!");
}
📝 同じ名前のメソッドを、異なる形で使い分けることができるのがオーバーロードの特徴です。
🔁 9.2 オーバーライド
🔄 「進化して技が強化された!」オーバーライドの本質
オーバーライドは、親クラスのメソッドを子クラスで書き換えることです。
たとえば、同じ「attack()」でも進化後はもっと強力にしたい!
public class Pokemon {
public void attack() {
System.out.println("ノーマルアタック!");
}
}
public class Pikachu extends Pokemon {
@Override
public void attack() {
System.out.println("ピカチュウの10まんボルト!");
}
}
📝 @Override
は、ちゃんとオーバーライドできているかをチェックするアノテーションです。
🌀 9.3 ポリモーフィズム(多態性)
🎨 「一つの技名で違う効果」ポリモーフィズムのすごさ
**ポリモーフィズム(多態性)**とは、親クラスの型で、子クラスのメソッドが実行されるしくみです。
Pokemon poke1 = new Pikachu(); // 親クラスの変数
poke1.attack(); // 実行時にはPikachuのattack()が使われる
📝 呼び出すときの型ではなく、**実際の中身の型(インスタンス)**でメソッドが決まります。
これを「動的バインディング」といいます。
✨️独自仕様:トレーナーによって異なる演出を加える例
public class Trainer {
public void usePokemon(Pokemon p) {
p.attack(); // 実際の種類に応じた攻撃を実行
}
}
ポケモンが何か分からなくても、共通のインターフェースで呼び出せる便利さがポリモーフィズムです。
🎯 9.4 まとめとテスト
✅ ポリモーフィズムのまとめ表
概念 | 説明 |
---|---|
オーバーロード | 同じ名前でも引数違いで使える |
オーバーライド | 親クラスのメソッドを書き換える |
ポリモーフィズム | 親型で子の処理を実行できる仕組み |
動的バインディング | 実行時に正しいメソッドを呼ぶ |
💻 総合サンプルコード
public class Pokemon {
public void attack() {
System.out.println("ノーマルアタック!");
}
public void attack(String move) {
System.out.println("「" + move + "」を使った!");
}
public void attack(String move, int times) {
System.out.println("「" + move + "」を" + times + "回使った!");
}
}
class Pikachu extends Pokemon {
@Override
public void attack() {
System.out.println("ピカチュウの10まんボルト!");
}
}
class Eevee extends Pokemon {
@Override
public void attack() {
System.out.println("イーブイのスピードスター!");
}
}
class Trainer {
public void usePokemon(Pokemon p) {
p.attack(); // ポリモーフィズムにより正しい技が使われる
}
}
public class Main {
public static void main(String[] args) {
Trainer ash = new Trainer();
Pokemon pika = new Pikachu();
Pokemon eevee = new Eevee();
ash.usePokemon(pika); // ピカチュウの技
ash.usePokemon(eevee); // イーブイの技
pika.attack("アイアンテール"); // オーバーロード(1)
pika.attack("でんこうせっか", 2); // オーバーロード(2)
}
}
🧩 このコードで、オーバーロード・オーバーライド・ポリモーフィズムの全てを体験できます!
🦄 第10章 幻のポケモンの謎!抽象クラスの世界
🧩 10.1 抽象クラスとは
👻 「図鑑に載っていない謎のポケモン」抽象クラスの特徴と役割
抽象クラス(abstract class)は、**「不完全な設計図」**のようなもの。
直接インスタンス化はできず、サブクラスで完成させてから使う必要があります。
public abstract class Pokemon {
String name;
String type;
public void introduce() {
System.out.println("私は " + name + "!タイプは " + type + "!");
}
public abstract void specialMove(); // 抽象メソッド:中身がない
}
📝 abstract
がついたメソッドには処理が書けません。サブクラスが実装を引き継ぐ前提です。
🧬 10.2 抽象クラスを継承する
🌟 「幻から実在へ」抽象メソッドの実装テクニック
抽象クラスを継承すると、abstractメソッドを必ず実装しなければなりません。
public class Mew extends Pokemon {
public Mew() {
name = "ミュウ";
type = "エスパー";
}
@Override
public void specialMove() {
System.out.println("ミュウのサイコキネシス!");
}
}
📝 このように、specialMove()
の中身を具象クラス(子クラス)で必ず記述します。
✨️独自仕様:「半分だけ実在する?」サブクラスも抽象クラスにする方法
public abstract class LegendaryPokemon extends Pokemon {
public abstract void summon(); // さらに抽象化された動作
}
📝 中間クラスでさらに抽象的な定義を追加することも可能です。
🗺 10.3 抽象クラスのクラス図
🖼 「幻のポケモンも図鑑に載せる」抽象クラスの表記法
以下は簡単なクラス図イメージです:
<<abstract>> Pokemon
+introduce()
+specialMove() ← abstract
▲
|
Mew : implements specialMove()
📝 <<abstract>>
は抽象クラスを意味し、三角矢印は継承を表します。
🎯 10.4 まとめとテスト
✅ 抽象クラスのまとめ表
項目 | 内容 |
---|---|
abstract class | 不完全な設計図、直接インスタンス化できない |
abstract method | 中身のないメソッド。子クラスで定義が必要 |
継承強制 | 抽象メソッドがあると、継承先で必ずオーバーライド |
中間抽象化 | 抽象クラス同士の継承も可能 |
💻 総合サンプルコード
public abstract class Pokemon {
protected String name;
protected String type;
public void introduce() {
System.out.println("私は " + name + "、タイプは " + type + " です!");
}
public abstract void specialMove(); // 抽象メソッド
}
class Mew extends Pokemon {
public Mew() {
this.name = "ミュウ";
this.type = "エスパー";
}
@Override
public void specialMove() {
System.out.println(name + "のサイコキネシス!");
}
}
public class Main {
public static void main(String[] args) {
Pokemon mystery = new Mew(); // 抽象クラスの型でインスタンスを扱う
mystery.introduce(); // 実装済みのメソッド
mystery.specialMove(); // オーバーライドされたメソッド
}
}
🧩 このコードでは、抽象クラスの利用・オーバーライド・ポリモーフィズムを体験できます!
🔗 第11章 ポケモンのタイプと能力!インタフェースの力
💡 11.1 インタフェースとは
🔍 「ひこうタイプ」「みずタイプ」インタフェースの定義と本質
Javaの**インタフェース(interface)**は、「ポケモンのタイプ」のようなものです。
同じ技を使える能力を複数のポケモンが共有することができます。
public interface Flyable {
void fly(); // ひこうタイプなら必ず飛べるようにする
}
📝 interface
は機能の契約書のようなもので、中身のないメソッドだけ定義します。
🧪 「複数のタイプを持つポケモン」クラスへのインタフェース実装
public class Charizard implements Flyable {
@Override
public void fly() {
System.out.println("リザードンは空を飛んだ!");
}
}
📝 implements
を使って、「このポケモンは飛べる」と明示的に宣言しています。
✨️独自仕様:「誰も変えられない特性」封印されたインタフェースの謎
インタフェースのメソッドはすべてpublic abstract
です。変更できません。
この特性が、共通の技を誰でも同じように使わせるためのルールを保っています。
🔁 11.2 インタフェース型への型変換
🔄 「タイプとしてのポケモン」インタフェース型の正体
Flyable flyingPokemon = new Charizard();
flyingPokemon.fly(); // リザードンのfly()が実行される
📝 インタフェース型の変数でオブジェクトを扱うことで、タイプに応じた共通操作が可能になります。
🎯 「みずタイプとして扱う」インタフェース型への変換テクニック
public interface WaterType {
void surf();
}
public class Vaporeon implements WaterType {
@Override
public void surf() {
System.out.println("シャワーズのなみのり!");
}
}
WaterType v = new Vaporeon(); のように使えます。
🎭 11.3 インタフェースによるポリモーフィズム
🧬 「タイプが違っても同じ技名」インタフェースで実現する多態性
public void useFly(Flyable f) {
f.fly(); // Flyableなら誰でも飛べる
}
📝 インタフェースを使えば、クラスに関係なく同じ機能を実行できます。
🧪 「実践!タイプ別技エフェクト」インタフェースの活用術
Flyable f1 = new Charizard();
Flyable f2 = new Pidgeot();
f1.fly(); // リザードン
f2.fly(); // ピジョット
クラスが違っても、fly()という共通の動作を使えるのが強みです。
🌐 11.4 インタフェースの継承
🔗 「特殊なタイプの誕生」インタフェース同士の継承の不思議
public interface FlyingWaterType extends Flyable, WaterType {
void dive();
}
📝 こうして「ひこう + みず」両方の能力をもった特殊なタイプを作ることもできます。
🧠 「進化しても受け継がれるタイプ」サブクラスに継承されるインタフェース
public class Gyarados implements FlyingWaterType {
@Override
public void fly() {
System.out.println("ギャラドスが舞い上がった!");
}
@Override
public void surf() {
System.out.println("ギャラドスのなみのり!");
}
@Override
public void dive() {
System.out.println("ギャラドスが深海に潜った!");
}
}
🎯 11.5 まとめとテスト
✅ インタフェースのまとめ表
項目 | 説明 |
---|---|
interface | 機能の契約、タイプのようなもの |
implements | インタフェースの機能を実装する |
多重実装 | 複数のタイプを同時に持つことが可能 |
ポリモーフィズム | クラスに関係なく共通操作が可能 |
💻 総合サンプルコード
public interface Flyable {
void fly();
}
public interface WaterType {
void surf();
}
public class Charizard implements Flyable {
@Override
public void fly() {
System.out.println("リザードンが空を飛んだ!");
}
}
public class Vaporeon implements WaterType {
@Override
public void surf() {
System.out.println("シャワーズがなみのりを使った!");
}
}
public class Gyarados implements Flyable, WaterType {
@Override
public void fly() {
System.out.println("ギャラドスが舞い上がった!");
}
@Override
public void surf() {
System.out.println("ギャラドスがなみのりを繰り出した!");
}
}
public class Main {
public static void main(String[] args) {
Flyable f = new Charizard();
WaterType w = new Vaporeon();
Flyable fw = new Gyarados();
f.fly();
w.surf();
fw.fly();
if (fw instanceof WaterType water) {
water.surf(); // Gyaradosとしてsurfも使える
}
}
}
🧩 この章では、「複数タイプ」「共通技」「型変換」などJavaのインタフェースのすべてが学べます!