ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
継承とは
継承は「is-a」関係を表す OOP の基本機構。「犬は動物の一種」「正方形は四角形の一種」のような階層を、コードで表現します。 親クラスのフィールド/メソッドを引き継ぎ、サブクラスで追加・上書きできます。
// Java での継承の基本
class Animal {
protected String name;
public Animal(String name) { this.name = name; }
public void eat() { System.out.println(name + " eats."); }
public void sound() { System.out.println("some sound"); }
}
class Dog extends Animal {
public Dog(String name) { super(name); } // 親コンストラクタ呼出
@Override
public void sound() { // メソッド上書き
System.out.println(name + ": ワン");
}
public void fetch() { // 新規メソッド
System.out.println(name + " runs after the ball");
}
}
Dog pochi = new Dog("ポチ");
pochi.eat(); // 親のメソッド利用可
pochi.sound(); // サブクラスの実装
pochi.fetch(); // サブクラス独自
// is-a 関係: Dog は Animal として扱える
Animal a = pochi; // OK (アップキャスト暗黙)
a.sound(); // "ポチ: ワン" (多態性、virtual dispatch)
各言語での継承構文
| 言語 | 構文 | 多重継承 |
|---|---|---|
| Java | class A extends B implements I1, I2 | 不可 (interface のみ多重) |
| C# | class A : B, I1, I2 | 不可 (interface のみ多重) |
| C++ | class A : public B, public C | 可 (virtual 継承で diamond 解決) |
| Python | class A(B, C): | 可 (C3 線形化) |
| PHP | class A extends B implements I1 | 不可 (trait で部分的に補完) |
| Kotlin | class A : B(), I1 | 不可 (interface のみ多重) |
| Ruby | class A < B | 不可 (Module の mixin) |
| Scala | class A extends B with T1 with T2 | trait で複数可 |
Diamond Problem (多重継承の罠)
下図のように 2 つの親が共通祖先を持つと、同名メソッドが衝突します:
Animal
/ \
Bird Mammal
\ /
Platypus ← どっちの walk() を継承?
各言語の解決策
| 言語 | 解決 |
|---|---|
| C++ | virtual 継承 + 明示的なスコープ解決 Bird::walk() |
| Python | C3 線形化 (MRO: Method Resolution Order)。super().__mro__ で確認 |
| Java / C# | そもそも多重継承不可。interface だけなら default メソッド衝突時に override 強制 |
| PHP | trait の insteadof で明示的選択 |
# Python: C3 線形化
class A:
def hello(self): print("A")
class B(A):
def hello(self): print("B")
class C(A):
def hello(self): print("C")
class D(B, C):
pass
D().hello() # B (MRO: D → B → C → A → object)
print(D.__mro__)
Composition Over Inheritance
近年の設計原則:継承より組み合わせ (Composition) を優先する。理由:
- 柔軟性: 実行時に挙動を入れ替えられる (Strategy パターン)
- Fragile Base Class 問題を回避 (親変更がサブクラス全部に波及)
- 多重継承の複雑さを避けられる
- テストしやすい (Mock しやすい)
// ❌ 継承で機能拡張 (Duck が Quack を直接実装)
abstract class Duck {
abstract void quack();
abstract void fly();
}
class MallardDuck extends Duck { ... }
class RubberDuck extends Duck { ... } // ゴム製のあひるは鳴かない → 困る
// ✅ Composition (機能を委譲)
interface QuackBehavior { void quack(); }
interface FlyBehavior { void fly(); }
class Duck {
private QuackBehavior quackBehavior;
private FlyBehavior flyBehavior;
public Duck(QuackBehavior q, FlyBehavior f) {
this.quackBehavior = q;
this.flyBehavior = f;
}
public void quack() { quackBehavior.quack(); }
public void fly() { flyBehavior.fly(); }
public void setQuackBehavior(QuackBehavior q) { this.quackBehavior = q; }
}
// 実行時に切替可能
Duck rubber = new Duck(new Squeak(), new NoFly());
Duck mallard = new Duck(new RealQuack(), new FlyWithWings());
SOLID の Liskov Substitution Principle (LSP)
「親クラス T の変数に、サブクラス S のインスタンスを入れ替えても、プログラムが正しく動くべき」という原則。違反例:
class Rectangle {
protected int width, height;
public void setWidth(int w) { this.width = w; }
public void setHeight(int h) { this.height = h; }
public int area() { return width * height; }
}
// 「正方形は長方形の一種」と思って継承するとバグる
class Square extends Rectangle {
@Override
public void setWidth(int w) {
this.width = w;
this.height = w; // 同期させる
}
@Override
public void setHeight(int h) {
this.width = h;
this.height = h;
}
}
// LSP 違反 → 親型変数で扱うとバグ
Rectangle r = new Square();
r.setWidth(5);
r.setHeight(10);
System.out.println(r.area()); // 100 を期待するも 100 ではなく 50? いや 100 …
// 実は両方 10x10 になり 100 になるが、Rectangle のインタフェース契約
// 「width と height は独立」を破っている → 別箇所でバグる
final / sealed / 継承の制限
// 1. final class: 継承禁止
final class String { ... } // 継承不可
// 2. final method: 上書き禁止
class Animal {
public final void breathe() { ... } // サブクラスで override 不可
}
// 3. private constructor + static factory
class Singleton {
private Singleton() {}
public static Singleton getInstance() { ... }
}
// 4. sealed class (Java 17+): 継承可能なサブクラスを限定
sealed abstract class Shape permits Circle, Square, Triangle {}
final class Circle extends Shape {}
final class Square extends Shape {}
final class Triangle extends Shape {}
// 第三者は Shape を継承不能 → pattern matching で網羅性チェック可能
Mixin (Python traits / PHP traits)
多重継承不可の言語で「コードの再利用」を実現する仕組み:
// PHP の trait
trait Loggable {
public function log(string $msg): void {
echo date('c') . " [" . static::class . "] $msg\n";
}
}
trait Cacheable {
public function cacheKey(): string {
return static::class . ':' . $this->id;
}
}
class User {
use Loggable, Cacheable;
public int $id = 1;
}
$u = new User();
$u->log("Hello"); // 2026-06-10T... [User] Hello
echo $u->cacheKey(); // User:1
設計指針 (まとめ)
- 継承は 1-2 階層まで。深い継承は読みづらく、Fragile Base Class が起きやすい
- 共通実装が大量にあるなら継承、共通インタフェースだけなら interface
- 挙動を実行時に切替えたいなら Composition + Strategy
- LSP を守る: 親型として扱われる前提のサブクラスを作る
- final / sealed を積極利用 → 想定外の継承を防ぐ
- クラス階層は「は (is-a)」で読んでみる。違和感があれば継承ではない
FAQ
Q: なぜ Java は多重継承を許さない?
A: Diamond Problem と Fragile Base Class の問題を避けるため。interface 多重実装 + default メソッドで代替可能。
Q: 継承と Composition、どちらを選ぶ?
A: 迷ったら Composition。「is-a」が自然な場合 + 親クラスがそれを前提に設計されているなら継承 OK。
Q: 親クラスの private フィールドはサブクラスで使える?
A: 使えません。サブクラスから使いたいなら protected (Java) / protected (C#) / _ プレフィクス (Python 慣習) で公開。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページ
子ページはありません
同階層のページ
- 基本的なルール
- 継承
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- IPv6とは|128bitアドレス・コロン16進表記/::省略・リンクローカル・SLAAC・デュアルスタック NEW 2026-06-22 12:34:44
- MAC アドレスフィルタリングの仕組みと限界 | ネットワーク入門 NEW 2026-06-22 12:19:10
- VPNとは|暗号トンネル・サイト間/リモートアクセス・IPsec/SSL-VPN/WireGuardを解説 NEW 2026-06-22 12:19:10
- WebRTC とは ブラウザ間 P2P の音声・映像・データ通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/2 とは 多重化・HPACK・バイナリフレーム | ネットワーク入門 NEW 2026-06-22 12:17:25
- Web通信プロトコル入門 HTTP/2・HTTP/3・WebSocket・gRPC・WebRTC | ネットワーク入門 NEW 2026-06-22 12:17:25
- gRPC とは HTTP/2 + Protocol Buffers の高速 RPC | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/3 (QUIC) とは UDP ベースの低遅延 Web 通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- WebSocket とは 全二重リアルタイム通信 ws/wss | ネットワーク入門 NEW 2026-06-22 12:17:25
- 証明書と認証局(CA)とは|X.509・信頼チェーン・DV/OV/EV・失効(CRL/OCSP)を解説 NEW 2026-06-22 12:17:24
- ファイアウォールとは|パケットフィルタ・ステートフル・DMZ・次世代FW(L4/L7)を解説 NEW 2026-06-22 12:17:24
- iptables/nftablesとは|テーブル・チェーン・ルール例・永続化をLinux視点で解説 NEW 2026-06-22 12:17:24
- HAProxy とは frontend/backend と設定例 | ネットワーク入門 NEW 2026-06-22 12:17:24
- CDN とは エッジキャッシュ・TTL・Cloudflare/CloudFront | ネットワーク入門 NEW 2026-06-22 12:17:24
- TLS/SSLの仕組み|ハンドシェイク・暗号スイート・前方秘匿性・証明書検証をわかりやすく解説 NEW 2026-06-22 12:17:24
コメントを削除してもよろしいでしょうか?