Menu
Coddy logo textTech

抽象クラスとメソッド

CoddyのPythonジャーニー「Object Oriented Programming」セクションの一部 — レッスン 25/64。

抽象クラスは、直接インスタンス化することができず、サブクラスで実装しなければならない抽象メソッドを含むクラスです。

フォームのように考えてみてください: 抽象クラスは、一部のフィールドが必須(抽象メソッド)で、一部が任意(具象メソッド)である必須のフォームコードのようなものです。フォーム自体を送信することはできません。まずすべての必須フィールドに入力する必要があります。同様に、サブクラスですべての抽象メソッドが実装されるまで、抽象クラスのインスタンスを作成することはできません。

abc モジュールをインポートして抽象クラスを作成します:

from abc import ABC, abstractmethod

抽象メソッドを持つ抽象クラスを作成します:

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass
    
    @abstractmethod
    def perimeter(self):
        pass
    
    def describe(self):
        return "This is a shape"  # 具体的なメソッド(実装を持つ)

@abstractmethod デコレータは、サブクラスで必ず実装しなければならないメソッドをマークします。これらはフォームにおける「必須項目」のようなものです。describe() のような通常のメソッドは実装を持つことができ、そのまま継承されます。これらは「既入力項目」のようなものです。

なぜ抽象クラスを使用するのでしょうか? これらはコントラクト(契約)を強制します。Shape クラスを作成する場合、「すべての図形は必ず面積と周囲の長さを計算できなければならない」と言っていることになります。これにより、重要なメソッドの実装を忘れてしまうといったバグを防ぐことができます。

抽象クラスのインスタンスを作成しようとしてみてください:

# これはエラーを引き起こします:
# shape = Shape()  # TypeError: 抽象クラスをインスタンス化できません

このエラーは意図的なものです。空のフォームを送信しようとするようなものです。Pythonは「まだ必須フィールド(areaメソッドとperimeterメソッド)を入力していません!」と言っています。

すべての抽象メソッドを実装する具体的なサブクラスを作成します。

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

これで「必要なフィールドをすべて埋めた」ことになります。つまり、area()perimeter() の両方を実装しました。Circle クラスは、インスタンス化可能な完全で具体的なクラスになりました。

これで、具象クラスのインスタンスを作成できます:

circle = Circle(5)
print(circle.area())
print(circle.perimeter())
print(circle.describe())  # 継承された具象メソッド

もう一つの具体的なサブクラスを作成します:

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

rectangle = Rectangle(4, 6)
print(rectangle.area())
print(rectangle.perimeter())

出力:

78.5
31.400000000000002
This is a shape
24
20

抽象クラスは、サブクラスが従わなければならない規約(コントラクト)を定義します。抽象クラスを作成するには、ABC@abstractmethod を使用します。サブクラスはすべての抽象メソッドを実装しなければならず、そうしない場合はそのサブクラスも抽象クラスになります。これにより一貫性が確保され、不完全な実装を防ぐことができます。

challenge icon

チャレンジ

中級

このチャレンジでは、支払い処理システムを実装します。

以下のファイルの実装を完了させる必要があります:

  • paymentmethod.py - バリデーションロジックを持つ抽象基底クラス
  • creditcard.py - クレジットカード支払いの実装
  • paypal.py - PayPal支払いの実装

各ファイルの TODO コメントに従って、必要な機能を実装してください。コメントは、抽象メソッドの作成、具体的なサブクラスの実装、およびファイル間の適切なインポート関係の確立をステップバイステップでガイドします。

driver.py ファイルには、実装が正しく動作することを確認するためのテストケースが含まれており、さまざまな支払いシナリオを処理し、各支払い方法の適切な詳細を表示します。

チートシート

抽象クラスは直接インスタンス化することはできず、サブクラスで実装しなければならない抽象メソッドを含みます。

abcモジュールをインポートします:

from abc import ABC, abstractmethod

抽象メソッドを持つ抽象クラスを作成します:

class Shape(ABC):
    @abstractmethod
    def area(self):
        pass
    
    @abstractmethod
    def perimeter(self):
        pass
    
    def describe(self):
        return "This is a shape"  # 具体的なメソッド(実装を持つ)

@abstractmethodデコレータは、サブクラスで実装しなければならないメソッドをマークします。通常のメソッドは実装を持つことができます。

抽象クラスはインスタンス化できません:

# これはエラーを引き起こします:
# shape = Shape()  # TypeError: Can't instantiate abstract class

すべての抽象メソッドを実装する具体的なサブクラスを作成します:

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

circle = Circle(5)
print(circle.area())        # 78.5
print(circle.describe())    # 継承された具体的なメソッド

重要なポイント:抽象クラスは、サブクラスが従わなければならないテンプレートを定義します。サブクラスはすべての抽象メソッドを実装しなければならず、そうしない場合はそのサブクラスも抽象クラスになります。

自分で試してみよう

from creditcard import CreditCard
from paypal import PayPal

# 実装をテストする - このテストコードは変更しないでください
cc = CreditCard("1234567890123456")
pp = PayPal("user@example.com")

# 有効な支払いを処理する
if cc.validate(100):
    print(cc.process_payment(100))
    print(cc.payment_details())

if pp.validate(200):
    print(pp.process_payment(200))
    print(pp.payment_details())

# 無効な金額を試す
if not pp.validate(0):
    print("Invalid payment amount")

# コメントを解除するとエラーが発生します:
# pm = PaymentMethod()  # 抽象クラスはインスタンス化できません
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

Object Oriented Programmingのすべてのレッスン