【Python基礎7】クラスとオブジェクト指向の基礎|プログラムの構造を理解しよう

オブジェクト指向とは何か?基本概念を理解しよう

オブジェクト指向プログラミング(OOP)の概要

オブジェクト指向プログラミング(OOP)は、データとそれに関する処理を1つのまとまり(オブジェクト)として扱うプログラミング手法です。この手法により、コードが再利用しやすくなり、保守性も向上します。

OOPの主な要素には次のものがあります:

  • クラス(Class): オブジェクトの設計図
  • オブジェクト(Object): クラスから作られる具体的な実体
  • メソッド(Method): オブジェクトが持つ関数
  • 属性(Attribute): オブジェクトが持つデータ

なぜオブジェクト指向が重要なのか?

  • コードの再利用がしやすい
  • プロジェクトが大規模でも整理しやすい
  • 実世界の概念をそのままプログラムに取り込める

クラスの定義とオブジェクトの生成

クラスの定義方法

クラスを定義するには、classキーワードを使います。クラス内に属性(データ)やメソッド(関数)を定義して、オブジェクトを生成します。

構文:

class クラス名:
    # クラスの属性やメソッドを定義する

基本的なクラスの例

次の例は、Personクラスを定義し、名前を表示するメソッドを持っています:

class Person:
    def greet(self):
        print("こんにちは!私は人間です。")

オブジェクトの生成

クラスからオブジェクトを作るには、クラス名に続けて丸括弧()を付けます。

person1 = Person()
person1.greet()

出力:

こんにちは!私は人間です。

コンストラクタ(__init__メソッド)の使い方

コンストラクタとは?

コンストラクタは、オブジェクトが生成されるときに自動で呼び出される特殊なメソッドです。Pythonでは、__init__メソッドがコンストラクタとして使われます。

例: オブジェクトが生成されるときに名前を設定する

class Person:
    def __init__(self, name):
        self.name = name
    
    def greet(self):
        print(f"こんにちは、私は{self.name}です。")

オブジェクト生成時に引数を渡す

person1 = Person("Taro")
person1.greet()

出力:

こんにちは、私はTaroです。

クラスの属性とメソッド

クラス属性とインスタンス属性の違い

  • クラス属性: クラス全体で共有されるデータ
  • インスタンス属性: オブジェクトごとに異なるデータ

例:

class Car:
    # クラス属性
    wheels = 4  

    def __init__(self, brand):
        # インスタンス属性
        self.brand = brand

car1 = Car("Toyota")
car2 = Car("Honda")

print(car1.brand)  # Toyota
print(car2.brand)  # Honda
print(Car.wheels)  # 4

出力:

Toyota  
Honda  
4

メソッドの定義

クラス内にメソッドを定義することで、オブジェクトに対して特定の動作を実行できます。

例:

class Dog:
    def __init__(self, name):
        self.name = name

    def bark(self):
        print(f"{self.name}が吠えています:ワンワン!")

dog1 = Dog("Pochi")
dog1.bark()

出力:

Pochiが吠えています:ワンワン!

継承(Inheritance)とコードの再利用

継承の概要

継承とは、既存のクラスを元に新しいクラスを作成し、元のクラスの属性やメソッドを引き継ぐ仕組みです。親クラス(スーパークラス)から子クラス(サブクラス)へと機能を継承することで、コードの再利用性が高まります。

構文:

class 子クラス(親クラス):
    # 追加の属性やメソッドを定義

継承の例

class Animal:
    def speak(self):
        print("動物が音を出します。")

class Dog(Animal):
    def speak(self):
        print("ワンワン!")

dog = Dog()
dog.speak()

出力:

ワンワン!

カプセル化とアクセス制御

カプセル化とは?

カプセル化とは、オブジェクトの内部データに直接アクセスできないようにし、メソッドを通じてのみデータにアクセスさせる仕組みです。これにより、不正なデータの変更を防ぎます。

プライベート変数とメソッド

プライベートな属性やメソッドは、クラス外からアクセスできないようにするため、変数名やメソッド名の先頭にアンダースコア_を2つ付けます。

例:

class BankAccount:
    def __init__(self, balance):
        self.__balance = balance  # プライベート変数

    def deposit(self, amount):
        self.__balance += amount

    def get_balance(self):
        return self.__balance

account = BankAccount(1000)
account.deposit(500)
print(account.get_balance())  # 1500

出力:

1500

ポリモーフィズム(多態性)の概念

ポリモーフィズムとは?

ポリモーフィズムとは、プログラミングにおいて「同じメソッド名で異なる動作を実現する」ことです。

「多態性」とも呼ばれ、同じインターフェース(メソッド名や関数名)を使って、異なるクラスのオブジェクトがそれぞれ固有の動作をすることができます。

ポリモーフィズムを利用することで、コードの再利用性や拡張性が向上します。

なぜポリモーフィズムが必要なのか?

  • 異なるクラスのオブジェクトを共通のコードで扱えるため、if文やswitch文の分岐を減らせます
  • 新しいクラスを追加しても、既存のコードを変更せずに動作を拡張できます。

ポリモーフィズムの種類

  1. メソッドのオーバーライド (Override)
    • 親クラスで定義されたメソッドを、子クラスで上書きして使うこと。
    • 継承を利用する場面でよく使われます。
  2. ダックタイピング (Duck Typing) – Python特有のポリモーフィズム
    • オブジェクトの型に依存せず、メソッドや属性の存在に依存します。
    • カモのように鳴き、カモのように歩くものはカモである」という考え方。
    • Pythonは「型」よりも「振る舞い」を重視するので、同じメソッド名を持っていれば、クラスに関係なく同様に扱えます。

ポリモーフィズムの例

class Bird:
    def speak(self):
        print("チュンチュン")

class Dog:
    def speak(self):
        print("ワンワン")

def make_sound(animal):
    animal.speak()

bird = Bird()
dog = Dog()

make_sound(bird)  # チュンチュン
make_sound(dog)   # ワンワン

出力:

チュンチュン  
ワンワン
  • make_sound 関数は、speak() メソッドを持つオブジェクトならどのクラスでも受け取れます。
  • Bird クラスと Dog クラスは、speak() という共通のメソッドを持っているため、make_sound 関数内でポリモーフィズムが実現されています。

メソッドのオーバーライドの例

class Animal:
    def speak(self):
        print("動物が鳴く")

class Cat(Animal):
    def speak(self):
        print("ニャーニャー")

class Dog(Animal):
    def speak(self):
        print("ワンワン")

def make_sound(animal):
    animal.speak()

cat = Cat()
dog = Dog()

make_sound(cat)  # ニャーニャー
make_sound(dog)  # ワンワン

出力:

ニャーニャー
ワンワン

ポリモーフィズムを使うメリット

  1. コードの拡張性
    • 新しいクラスを追加しても、既存の関数やメソッドを変更する必要がありません。
    • 例:新しく class Cow(Animal): を追加して speak() メソッドを定義すれば、make_sound() をそのまま使えます。
  2. コードの再利用性
    • 同じ処理を共通化でき、重複コードを減らせます。
  3. 柔軟な設計
    • オブジェクトの型に依存せずにメソッドを呼び出せるので、より柔軟なコードが書けます。

ポリモーフィズムの注意点

def make_sound(animal):
    if hasattr(animal, 'speak'):
        animal.speak()
    else:
        print("speak() メソッドがありません")

まとめと次のステップ

クラスとオブジェクト指向プログラミングは、Pythonを使って効率的で拡張性のあるプログラムを作成するために不可欠な知識です。クラスの定義、メソッドの使い方、継承やカプセル化など、基本的な概念を理解することで、複雑なプログラムをシンプルに設計することが可能です。次のステップとして、オブジェクト指向を使った小さなプロジェクトに挑戦し、実際に学んだ知識を応用してみましょう!