この記事では、Python のオブジェクト指向プログラミング(OOP)の基本である「Class(クラス)」と「継承(Inheritance)」について、初心者にもイメージしやすいように解説します。実際のコード例を交えながら学んでいきましょう。
1. オブジェクト指向プログラミング(OOP)とは?
まずは オブジェクト指向プログラミング(OOP) の基本概念から説明します。
- オブジェクト:データ(属性)と処理(メソッド)をまとめたもの。
- クラス:オブジェクトの設計図。どんな属性・メソッドを持つかを定義する。
- インスタンス:クラスから生成された実体(オブジェクト)。
よりイメージしやすいように、レシピに例えてみると
- クラス = レシピ(どんな材料が必要で、どう調理するか)
- インスタンス = 実際に作った料理
レシピがあれば、同じ手順で何度でも料理を再現できますよね。クラスも同じく、「これを持っている・これができる」オブジェクトを何度でも作れる設計図になります。
2. Python でのクラス定義の基本
Python で最もシンプルなクラスの書き方を見てみましょう。
class Dog:
# クラス変数(すべてのインスタンスで共有)
species = "Canis familiaris"
def __init__(self, name, age):
# インスタンス変数(個々のインスタンス固有)
self.name = name
self.age = age
def bark(self):
print(f"{self.name} says: ワンワン!")
__init__:インスタンス生成時に呼ばれる初期化メソッド。self:インスタンス自身を指すキーワード。必ず第一引数に書きます。
インスタンス化してみよう
dog1 = Dog("ポチ", 3)
dog2 = Dog("ハチ", 5)
print(dog1.name, dog1.age) # ポチ 3
print(dog2.name, dog2.age) # ハチ 5
dog1.bark() # ポチ says: ワンワン!
dog2.bark() # ハチ says: ワンワン!
3. 継承(Inheritance)
ここからが本題の「継承」です。
継承とは、あるクラス(親クラス/スーパークラス)の機能を引き継いで、新しいクラス(子クラス/サブクラス)を作る仕組みです。
こちらも具体例でイメージをしましょう。
- 親クラス:自動車
- エンジン、ホイール、ハンドル、といった基本的な部品と機能を持つ
- 子クラス:スポーツカー
- 「自動車」をベースに「ターボエンジン」や「低重心シャーシ」などを追加
親クラスに書いた処理・属性はそのまま使え、必要に応じて追加や上書き(オーバーライド)も可能です。
4. Python での継承の書き方
先ほどの Dog クラスを親として、GuardDog(番犬)という子クラスを作ってみましょう。
class GuardDog(Dog):
def __init__(self, name, age, guard_area):
# super() で親クラスの __init__ を呼び出す
super().__init__(name, age)
self.guard_area = guard_area # 子クラス独自の属性
# 親クラスの bark をオーバーライド(上書き)
def bark(self):
print(f"{self.name} ({self.guard_area}) says: ガルルル…")
# 子クラス独自のメソッド
def guard(self):
print(f"{self.name} is guarding {self.guard_area}!")
class GuardDog(Dog):で継承を指定。super().__init__(…)で親クラスの初期化処理を呼び出します。- 必要に応じてメソッドを上書き(オーバーライド)したり、独自メソッドを追加できます。
動かしてみる
gd = GuardDog("タロー", 4, "倉庫")
print(gd.species) # Canis familiaris(親から継承したクラス変数)
gd.bark() # タロー (倉庫) says: ガルルル…
gd.guard() # タロー is guarding 倉庫!
5. 継承のメリット
- コードの再利用
親クラスに書いた機能をそのまま使えるので、同じ処理を何度も書かずに済みます。 - 保守性の向上
基本機能は親クラスにまとめておくことで、バグ修正や機能追加を一か所で済ませられます。 - 拡張しやすい設計
子クラスで必要な機能だけ追加・上書きすればよいので、新しい要件に柔軟に対応できます。
6. 継承時の注意点
- 多重継承(複数の親クラスを持つ)は強力ですが、メソッド解決順序(MRO)が複雑になりやすいので慎重に。
- オーバーライドしすぎない:親クラスと子クラスで同じメソッド名を多用すると、どの処理が呼ばれるか分かりにくくなることがあります。
- super() の使い方:必ず正しい引数で呼び出し、親クラスの初期化を飛ばさないように注意しましょう。
7. 多重継承の例(応用編)
class Flyable:
def fly(self):
print("飛んでいます!")
class Swimmable:
def swim(self):
print("泳いでいます!")
# 多重継承クラス
class Duck(Flyable, Swimmable):
def quack(self):
print("ガーガー")
d = Duck()
d.quack() # ガーガー
d.fly() # 飛んでいます!
d.swim() # 泳いでいます!
ポイント:Python の MRO によって、Duck がどのクラスからどのメソッドを取得するかが決まります。多重継承は便利ですが、複雑化しやすい点に注意しましょう。
8. 実践的な設計例:ゲームキャラクター
例えば RPG のキャラクターを設計する場合を考えてみます。
class Character:
def __init__(self, name, hp):
self.name = name
self.hp = hp
def attack(self, target):
print(f"{self.name} attacks {target.name}!")
class Warrior(Character):
def __init__(self, name, hp, strength):
super().__init__(name, hp)
self.strength = strength
def attack(self, target):
damage = self.strength * 2
target.hp -= damage
print(f"{self.name} の強力な攻撃! {target.name} に {damage} ダメージ!")
class Mage(Character):
def __init__(self, name, hp, mp):
super().__init__(name, hp)
self.mp = mp
def cast_spell(self, target):
cost = 10
if self.mp >= cost:
self.mp -= cost
target.hp -= 15
print(f"{self.name} の魔法! {target.name} に 15 ダメージ!")
else:
print("MPが足りません!")
WarriorとMageはともにCharacterを継承し、共通のnameやhp、attackメソッドを持つ。- 個別の攻撃ロジック(物理 vs 魔法)を子クラスで定義しています。
9. 継承と組み合わせるデザインパターン
継承をさらに活かすため、よく使われるデザインパターンを紹介します。
- Template Method パターン
- 親クラスで大まかな処理の流れ(テンプレート)を定義し、細かい実装は子クラスに任せる。
- Factory Method パターン
- オブジェクト生成を親クラスに委譲し、子クラスで生成する具体的なクラスを決定する。
- Strategy パターン
- アルゴリズムをクラスとして分離し、動的に差し替えられるようにする。
これらはいずれも「継承」と「ポリモーフィズム(多態性)」を活用した強力な手法です。
10. まとめと次の一歩
- クラス は「設計図」、インスタンス は「実物」。
- 継承 によってコードを再利用し、保守性・拡張性が向上する。
- オーバーライド や super() の使い方を正しく理解することが大切。
- 多重継承 や デザインパターン によって、さらに柔軟で強力な設計が可能に。
これで Python の Class と継承の基本はマスターできました!ぜひご自分で小さなプロジェクトを作って、親子クラスの設計を試してみてください。













コメントを残す