プログラミング言語にはいくつかのパラダイムがありますが、その中でオブジェクト指向プログラミング(OOP)は非常に強力で、柔軟性の高い方法の一つです。OOPは、プログラムを「オブジェクト」の集まりとして捉え、そのオブジェクトが相互に作用し合うことでプログラムが動作するという考え方に基づいています。この章では、Pythonにおけるオブジェクト指向プログラミングの基礎、クラスとオブジェクトの関係、メソッドと属性、そして継承とポリモーフィズムについて学びます。
OOPの中心的な概念は「クラス」と「オブジェクト」です。まず、これらの用語について理解しましょう。
具体的な例を見てみましょう。たとえば、クラスを使って「犬」を表すことができます。このクラスには「名前」や「年齢」といった属性があり、「吠える」といったメソッドを持つかもしれません。
class Dog:
def __init__(self, name, age):
# クラスのコンストラクタで、オブジェクトが生成されたときに呼び出される
self.name = name
self.age = age
def bark(self):
# メソッドで、犬が吠えるという動作を表現
print(f"{self.name}が吠えた!ワンワン!")
# クラスからオブジェクトを生成する
my_dog = Dog("ポチ", 3)
print(my_dog.name) # ポチ
print(my_dog.age) # 3
# メソッドを呼び出す
my_dog.bark() # ポチが吠えた!ワンワン!
上記のコードでは、Dogというクラスが定義されており、そのクラスからmy_dogというオブジェクトが生成されています。__init__メソッドは、クラスからオブジェクトが生成される際に呼び出され、オブジェクトの初期化を行います。オブジェクトの属性にはself.nameやself.ageがあり、barkというメソッドはオブジェクトに「吠える」という動作を提供しています。
クラスの中では、データ(属性)と機能(メソッド)を一緒に扱うことができます。Pythonでは、属性はオブジェクトに関連付けられた変数であり、メソッドはオブジェクトに関連付けられた関数です。クラス内の全てのメソッドの最初の引数にはselfが必要です。このselfは、そのメソッドが呼び出されたオブジェクト自身を指します。selfを使うことで、オブジェクトの属性にアクセスしたり、他のメソッドを呼び出すことができます。
属性は、クラス内で定義され、selfキーワードを使ってオブジェクトに紐づけられます。self.attribute_nameという形で、属性にアクセスしたり値を設定します。
class Cat:
def __init__(self, name, breed):
self.name = name # オブジェクトの属性「名前」を定義
self.breed = breed # オブジェクトの属性「種類」を定義
# クラスからオブジェクトを生成
my_cat = Cat("タマ", "シャム")
# 属性にアクセス
print(my_cat.name) # タマ
print(my_cat.breed) # シャム
メソッドはクラスの中で定義された関数です。クラスのメソッドにはselfを必ず引数として含め、オブジェクト自身を操作するために使います。
class Cat:
def __init__(self, name, breed):
self.name = name
self.breed = breed
def meow(self):
print(f"{self.name}が鳴いた!ニャー!")
# オブジェクトの生成
my_cat = Cat("タマ", "シャム")
my_cat.meow() # タマが鳴いた!ニャー!
上記の例では、meowというメソッドを使って、Catオブジェクトが「鳴く」という動作を持たせています。このようにして、クラスにさまざまな動作(メソッド)を定義することができ、それをオブジェクトに実装することができます。
オブジェクト指向プログラミングのもう一つの強力な特徴は、継承とポリモーフィズムです。
継承は、既存のクラスをベースに新しいクラスを作ることができる機能です。新しいクラス(サブクラス)は、既存のクラス(スーパークラス)の属性やメソッドを引き継ぐことができます。これにより、コードの再利用が容易になり、クラス間の共通機能を簡単に定義できます。
たとえば、「犬」クラスと「猫」クラスに共通する部分を「動物」クラスにまとめ、それぞれのクラスで継承させることができます。
# スーパークラス(親クラス)
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
print(f"{self.name}が何かを話した!")
# サブクラス(子クラス)
class Dog(Animal):
def speak(self):
print(f"{self.name}が吠えた!ワンワン!")
class Cat(Animal):
def speak(self):
print(f"{self.name}が鳴いた!ニャー!")
# オブジェクトを生成
my_dog = Dog("ポチ")
my_cat = Cat("タマ")
my_dog.speak() # ポチが吠えた!ワンワン!
my_cat.speak() # タマが鳴いた!ニャー!
この例では、Animalクラスを継承するDogクラスとCatクラスを定義しています。継承を使うことで、共通する部分(name属性やspeakメソッド)をAnimalクラスにまとめ、DogやCatのクラスでは独自の振る舞い(それぞれのspeakメソッド)を持たせることができます。
ポリモーフィズムとは、異なるクラスのオブジェクトが同じメソッドを持ち、同じインターフェースでそれらのメソッドを呼び出すことができる仕組みです。これは、例えば、DogクラスやCatクラスのように、異なるクラスのオブジェクトに対しても同じspeakメソッドを呼び出すことができ、オブジェクトによって異なる結果が得られることを意味します。
animals = [Dog("ポチ"), Cat("タマ")]
for animal in animals:
animal.speak()
この例では、DogとCatという異なるクラスのオブジェクトに対して、同じspeakメソッドを呼び出しています。各オブジェクトは、それぞれのクラスで定義されたメソッドを実行し、異なる結果を返しています。これがポリモーフィズムの一例です。
まとめ
Pythonにおけるオブジェクト指向プログラミングの基礎的な概念である「クラスとオブジェクト」、「メソッドと属性」、そして「継承とポリモーフィズム」の解説です。オブジェクト指向の考え方を理解することで、コードの構造を柔軟にし、再利用可能で保守性の高いプログラムを作成することができるようになります。