生成AIに聞いてみた、Pythonのオブジェクト指向プログラミング

https://qiita.com/Akuuuun/items/af6e00a07b9422dcd054

# 6. オブジェクト指向プログラミング
   - クラスとオブジェクト
   - カプセル化
   - 継承
   - ポリモーフィズム
   - 抽象クラスとインターフェース

オブジェクト指向プログラミング（OOP）は、プログラミングのパラダイムの一つで、データとそのデータを操作する機能を一つの「オブジェクト」としてまとめる考え方です。Pythonはオブジェクト指向プログラミングをサポートしており、その概念を効果的に活用できます。以下、OOPの主要な概念について、Pythonのサンプルコードを交えて説明します。

## 1. クラスとオブジェクト

クラスは、オブジェクトの設計図やテンプレートのようなものです。オブジェクトは、クラスのインスタンス（実体）です。

```python
class Dog:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    def bark(self):
        return f"{self.name}が吠えました：ワン！"

# オブジェクトの作成
my_dog = Dog("ポチ", 3)
print(my_dog.name)    # ポチ
print(my_dog.bark())  # ポチが吠えました：ワン！
```

この例では、`Dog`というクラスを定義し、`name`と`age`という属性、そして`bark`というメソッドを持たせています。

## 2. カプセル化

カプセル化は、データ（属性）と、そのデータを操作するメソッドをまとめることです。また、データの直接アクセスを制限することで、データの整合性を保護します。

```python
class BankAccount:
    def __init__(self, balance):
        self.__balance = balance  # プライベート属性
    
    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            return True
        return False
    
    def withdraw(self, amount):
        if 0 < amount <= self.__balance:
            self.__balance -= amount
            return True
        return False
    
    def get_balance(self):
        return self.__balance

account = BankAccount(1000)
print(account.get_balance())  # 1000
account.deposit(500)
print(account.get_balance())  # 1500
account.withdraw(200)
print(account.get_balance())  # 1300
# print(account.__balance)    # これはエラーになります
```

この例では、`__balance`をプライベート属性とし、直接アクセスできないようにしています。代わりに、`deposit`、`withdraw`、`get_balance`メソッドを通じて残高を操作・取得します。

## 3. 継承

継承は、既存のクラス（親クラス）の属性やメソッドを新しいクラス（子クラス）に引き継ぐ機能です。

```python
class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return f"{self.name}が吠えました：ワン！"

class Cat(Animal):
    def speak(self):
        return f"{self.name}が鳴きました：ニャー！"

dog = Dog("ポチ")
cat = Cat("タマ")

print(dog.speak())  # ポチが吠えました：ワン！
print(cat.speak())  # タマが鳴きました：ニャー！
```

この例では、`Animal`クラスを親クラスとし、`Dog`と`Cat`クラスがそれを継承しています。各子クラスは`speak`メソッドをオーバーライド（再定義）しています。

## 4. ポリモーフィズム

ポリモーフィズムは、同じインターフェース（メソッド名）で異なる挙動を実現する機能です。

```python
def animal_sound(animal):
    print(animal.speak())

dog = Dog("ポチ")
cat = Cat("タマ")

animal_sound(dog)  # ポチが吠えました：ワン！
animal_sound(cat)  # タマが鳴きました：ニャー！
```

この例では、`animal_sound`関数は`Animal`クラスのインスタンスを期待していますが、実際には`Dog`や`Cat`のインスタンスを渡しても正しく動作します。これがポリモーフィズムの一例です。

## 5. 抽象クラスとインターフェース

抽象クラスは、直接インスタンス化されることを意図していないクラスで、他のクラスが継承して使用することを前提としています。Pythonでは、`abc`モジュールを使用して抽象クラスを定義できます。

```python
from abc import ABC, abstractmethod

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass

class Rectangle(Shape):
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def area(self):
        return self.width * self.height

class Circle(Shape):
    def __init__(self, radius):
        self.radius = radius
    
    def area(self):
        return 3.14 * self.radius ** 2

# shape = Shape()  # これはエラーになります
rectangle = Rectangle(5, 3)
circle = Circle(2)

print(rectangle.area())  # 15
print(circle.area())     # 12.56
```

この例では、`Shape`は抽象クラスで、`area`メソッドを持つことを要求しています。`Rectangle`と`Circle`クラスは`Shape`を継承し、それぞれ`area`メソッドを実装しています。

これらの概念を理解し、適切に使用することで、より構造化され、保守性の高い、再利用可能なコードを書くことができます。オブジェクト指向プログラミングは、大規模なプロジェクトや複雑なシステムの設計に特に有効です。