【Python】レッスン5-09:抽象クラスを理解しよう

ながみえ
【Python学習記事のアイキャッチ画像】Lesson5-9 抽象クラスを理解しよう

一つ前のLessonではモジュールについて学習しました。

今回は抽象クラスについて見ていきましょう。

Lesson1:基礎文法編
Lesson2:制御構造編
Lesson3:関数とスコープ編

Lesson4:データ構造編
Lesson5:オブジェクト指向編
・Lesson5-1:クラスの基本を理解しよう
・Lesson5-2:メソッドの基本を理解しよう
・Lesson5-3:カプセル化を理解しよう
・Lesson5-4:プロパティを理解しよう
・Lesson5-5:クラスの継承を理解しよう
・Lesson5-6:メソッドのオーバーライドを理解しよう
・Lesson5-7:静的メソッドを理解しよう
・Lesson5-8:モジュールを使いこなそう
・Lesson5-9:抽象クラスを理解しよう ◁今回はココ
・Lesson5-10:ミックスインを理解しよう
・Lesson5-11:データクラスを理解しよう
・練習問題5-1:モンスター捕獲ゲームを作ろう
・練習問題5-2:モンスターとのバトルゲームを作ろう
次のステップ:Python基礎習得者にお勧めの道5選(実務or副業)

<<前のページ

【Python学習記事のアイキャッチ画像】Lesson5-8 モジュールを使いこなそう

Pythonの記事一覧

Python学習カテゴリの親ページ用アイキャッチ画像(テキスト&問題集)、記事一覧へのリンク案内

次のページ>>

【Python学習記事のアイキャッチ画像】Lesson5-10 ミックスインを理解しよう

抽象クラスとは?共通機能の定義と実装ルールの設定方法

プログラムを作成する際、コードを再利用しやすく、メンテナンスしやすく設計することが重要です。

抽象クラスはその設計に役立つ概念で、共通の基盤を提供しつつ具象クラスでの独自実装を促す仕組みです。

【Python】勉強猫がノートパソコンを前にして学習を始める様子。記事内の学習スタート用イラスト

抽象クラスとは|@abstractmethodデコレーターの使い方

抽象クラスとは、直接インスタンス化されることを想定しない基底クラス(継承されることを前提としたクラス)です。

主に以下のような目的で使用されます:

  • 子クラスで実装する必要がある共通のメソッドを定義
  • 設計の一貫性を保証

Pythonでは abcモジュール(Abstract Base Classesの略)に含まれる ABCクラス と @abstractmethodデコレーター を使用します。

以下に基本的な構文を示します:

from abc import ABC, abstractmethod # abcモジュールからABCクラスとabstractmethodデコレータをインポート

class クラス名(ABC):		 # ABCクラスを継承した抽象クラスAnimalを定義
    @abstractmethod			# 抽象メソッドであることを表すデコレーター
    def メソッド名(self):	# 抽象メソッド(必ずオーバーライドされないといけない)

抽象メソッドは具体的な処理を持たず、子クラスからオーバーライドされる前提となっています。

また、抽象クラスを直接インスタンス化しようとするとエラーが発生します。

抽象クラスの使用コード例

以下は具体的な使用例です。

動物クラスを基底クラスとして作成し、子クラスで動作を具体化します。

from abc import ABC, abstractmethod	# abc関連のモジュールのインポート

class Animal(ABC):		# 抽象クラスの定義
    @abstractmethod		# デコレーター
    def speak(self):	# 抽象メソッドの定義
        pass
    @abstractmethod		# デコレーター
    def move(self):		# 抽象メソッドの定義
        pass

class Dog(Animal):		# Animalクラスを継承したDogクラスの定義
    def speak(self):	# 抽象メソッドの実装 & オーバーライド
        return "Woof!"
    def move(self):		# 抽象メソッドの実装 & オーバーライド
        return "Runs on four legs"

class Bird(Animal):		# Animalクラスを継承したBirdクラスの定義
    def speak(self):	# 抽象メソッドの実装 & オーバーライド
        return "Chirp!"
    def move(self):		# 抽象メソッドの実装 & オーバーライド
        return "Flies in the sky"

dog = Dog()			# インスタンス生成
bird = Bird()		# インスタンス生成

print(dog.speak())	# Woof!
print(dog.move())	# Runs on four legs
print(bird.speak())	# Chirp!
print(bird.move())	# Flies in the sky

# 二つの子クラスは同じ抽象クラスを継承したが、出力はクラスごとに異なる

この例ではAnimalという抽象クラスを基にしてDogBirdというクラスを作成しています。

子クラスでAnimalクラスのメソッドを実装することで、各動物の特性を定義できます。

Woof!
Runs on four legs
Chirp!
Flies in the sky

まとめ

【初心者向け】Pythonのオブジェクト指向を分かりやすくまとめた概念図。 特にクラスの継承、オーバーライド、抽象クラス、ミックスインクラス、データクラス、静的メソッドの関係性を視覚的に理解できるようまとめている。

ここまでで、抽象クラス(ABC)の役割と、@abstractmethod で実装必須メソッドを宣言する基本手順を確認しました。

抽象クラスは「共通API=契約」を先に定め、未実装のままではインスタンス化できないことで、サブクラス側に実装を促します。

加えて、共通の下地(具象メソッドやテンプレートメソッド)を親に置き、差分だけを子で実装する設計も可能です。

この学習により、API を統一しつつ多態性を安全に活かすクラス設計、プラグイン/戦略パターンのような差し替え可能な構成、そして未実装の取りこぼしを型レベルで防ぐ運用ができるようになりました。

まずは既存の共通処理を「契約」として切り出し、抽象メソッドで “必ず実装すべき点” を明示するところから一歩ずつ進めていきましょう。

Q
サイト改善アンケート|ご意見をお聞かせください(1分で終わります)

本サイトでは、みなさまの学習をよりサポートできるサービスを目指しております。
そのため、みなさまの「プログラミングを学習する理由」などをアンケート形式でお伺いしています。

1分だけ、ご協力いただけますと幸いです。

【Python】サイト改善アンケート
1.このサイトをどのように活用していますか?また、今後どのように活用したいですか?
5.気になっているサービス・商品があれば教えてください。
(複数選択可)
※ 特定の記事に関する内容の場合は、記事番号(Python Lesson〇-〇)をご記入願います。 また、ご質問はここではなく問い合わせフォームからお願いします。

練習問題:抽象クラスを使ってみよう

この記事で学習した「抽象クラス」を復習する練習問題に挑戦しましょう。

【Python】勉強猫がノートパソコンに向かい、練習問題に挑戦する様子。記事内の休憩用イラスト

問題|犬と鳥の動作をクラスで表現しよう

動物を表す抽象クラスを用意し、その契約(鳴き声・移動)の実装を犬と鳥のクラスに任せるミニプログラムを作成します。

最後に、生成したオブジェクトから鳴き声と移動方法を取得して表示してください。

以下の要件に従ってコードを完成させてください。

  • abc モジュールを用い、抽象クラス Animal を定義する。
    AnimalABC を継承し、make_sound(self)move(self)@abstractmethod で宣言する(抽象メソッド)。
  • Dog クラスと Bird クラスを Animal から継承し、各抽象メソッドを文字列を戻り値として実装する。
  • Dog.make_sound() は「ワンワン!」、Dog.move() は「走り回る」。
  • Bird.make_sound() は「ピヨピヨ!」、Bird.move() は「空を飛ぶ」。
  • スクリプト末尾で DogBird のインスタンスを生成し、鳴き声と移動方法を表示する。

ただし、以下のような実行結果となるコードを書くこと。

犬の鳴き声: ワンワン!
犬の移動方法: 走り回る
鳥の鳴き声: ピヨピヨ!
鳥の移動方法: 空を飛ぶ

ヒント|難しいと感じる人だけ見よう

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

Q
ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。

1:抽象クラスを定義し、「鳴き声」と「移動」の実装契約を宣言する
 ・抽象クラスは専用モジュールを使い、基底クラスは ABC を継承する
 ・必ず実装させたいメソッド名は make_sound と move にし、抽象メソッドとして宣言する
 ・抽象メソッドは本体を持たず、中身は空(実装はサブクラス側で行う)

2:犬と鳥のサブクラスで抽象メソッドを具体化し、振る舞いを与える
 ・抽象メソッドと同じシグネチャ(名前・引数)で実装する
 ・返すのは文字列(鳴き声/移動方法)で、表示は後段に任せる
 ・犬と鳥で意味のある違いを持たせ、共通の呼び出しで比較できるようにする

3:インスタンスを生成し、共通インターフェースで呼び出して結果を表示する
 ・まず犬と鳥のインスタンスを1つずつ生成する
 ・両者に対して make_soundmove を同じ手順で呼び出す
 ・返ってきた文字列に説明ラベルを付けて表示すると読みやすい

Q
ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

'''(穴埋め) abcモジュールから ABC と abstractmethod をインポートする行を書く '''

# 動物の基底クラス(抽象クラス)
class Animal('''(穴埋め)'''):
    @abstractmethod
    def make_sound(self):	# 動物の鳴き声を出力する抽象メソッド
        pass

    @'''(穴埋め)'''
    def move(self):	# 動物がどのように移動するかを定義する抽象メソッド
        pass

# 犬クラス(Animalを継承)
class Dog(Animal):
    def make_sound(self):
        return "ワンワン!"
    def move(self):
        return "走り回る"

# 鳥クラス(Animalを継承)
class Bird(Animal):
    def make_sound(self):
        return "ピヨピヨ!"
    def move(self):
        return "空を飛ぶ"

# 犬と鳥のインスタンスを生成
dog = Dog()
bird = Bird()

# 犬の鳴き声と動作
print("犬の鳴き声:", dog.make_sound())
print("犬の移動方法:", dog.move())

# 鳥の鳴き声と動作
print("鳥の鳴き声:", bird.make_sound())
print("鳥の移動方法:", bird.move())

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。

解答例|動物クラスの抽象インターフェースプログラム

例えば以下のようなプログラムが考えられます。

Q
正解コード
from abc import ABC, abstractmethod  # abcモジュールをインポート

# 動物の基底クラス(抽象クラス)
class Animal(ABC):
    @abstractmethod
    def make_sound(self):	# 動物の鳴き声を出力する抽象メソッド
        pass

    @abstractmethod
    def move(self):	# 動物がどのように移動するかを定義する抽象メソッド
        pass

# 犬クラス(Animalを継承)
class Dog(Animal):
    def make_sound(self):
        return "ワンワン!"
    def move(self):
        return "走り回る"

# 鳥クラス(Animalを継承)
class Bird(Animal):
    def make_sound(self):
        return "ピヨピヨ!"
    def move(self):
        return "空を飛ぶ"

# 犬と鳥のインスタンスを生成
dog = Dog()
bird = Bird()

# 犬の鳴き声と動作
print("犬の鳴き声:", dog.make_sound())
print("犬の移動方法:", dog.move())

# 鳥の鳴き声と動作
print("鳥の鳴き声:", bird.make_sound())
print("鳥の移動方法:", bird.move())

解答例の解説|動物クラスの抽象インターフェースプログラムの考え方

解答例の詳細解説は以下の通りです。

Q
詳細解説

抽象クラスの定義

from abc import ABC, abstractmethod  # abcモジュールをインポート

# 動物の基底クラス(抽象クラス)
class Animal(ABC):
    @abstractmethod
    def make_sound(self):	# 動物の鳴き声を出力する抽象メソッド
        pass

    @abstractmethod
    def move(self):	# 動物がどのように移動するかを定義する抽象メソッド
        pass

ここでは、動物という概念を直接は作れない“型の設計図”として用意します。
抽象クラスを使うと、派生クラスが必ず備えるべきメソッドを先に約束として示せます。
具体的には、鳴き声と移動の2つを「ここは各動物で必ず実装してください」という契約にしておきます。
こうしておくと、犬や鳥のようなサブクラスを作るときに、必要なメソッドを漏れなく実装でき、共通の呼び出し方で扱えるようになります。
抽象メソッドは中身を持たないため、この時点ではインスタンス化はできません(未実装のまま使おうとするとエラーになります)。

子クラスの定義

# 犬クラス(Animalを継承)
class Dog(Animal):
    def make_sound(self):
        return "ワンワン!"
    def move(self):
        return "走り回る"

# 鳥クラス(Animalを継承)
class Bird(Animal):
    def make_sound(self):
        return "ピヨピヨ!"
    def move(self):
        return "空を飛ぶ"

ここでは、抽象クラスで約束したメソッドに中身を与えて、実際に動く振る舞いへ落とし込みます。
犬と鳥は同じ名前のメソッドを持ちますが、返す内容はそれぞれの動物にふさわしいテキストになります。こうしておくと、呼び出し側は型ごとの差を意識せず同じ操作で扱えます。
つまり「同じインターフェース、違う結果」という多態性を、短い例で体験できるわけです。
ここでは表示は行わず、文字列を返すだけにしておくことで、出力の方法や場所は後段の処理に委ねられます。

インスタンス生成と出力

# 犬と鳥のインスタンスを生成
dog = Dog()
bird = Bird()

# 犬の鳴き声と動作
print("犬の鳴き声:", dog.make_sound())
print("犬の移動方法:", dog.move())

# 鳥の鳴き声と動作
print("鳥の鳴き声:", bird.make_sound())
print("鳥の移動方法:", bird.move())

ここでは、犬と鳥のオブジェクトを実際に作り、抽象クラスで約束した同じメソッド名を使って振る舞いを取り出し、画面に表示します。
どちらのオブジェクトも同じ呼び出し方で扱えるのは、基底に共通の契約があるからです。
返ってくるのは文字列なので、表示用のラベル(「犬の鳴き声: 」「鳥の移動方法: 」など)を添えて出力すれば、結果が分かりやすくなります。
型ごとの違いは内部の実装に任せ、呼び出し側は同じ手順で処理できる——これが多態性のメリットです。

もっと分かりやすい学習サイトにするために

この記事を読んで「ここが分かりにくかった」「ここが難しかった」等の意見を募集しています。

世界一わかりやすいPython学習サイトにするため、ぜひ 問い合わせフォーム からご意見下さい。

<<前のページ

【Python学習記事のアイキャッチ画像】Lesson5-8 モジュールを使いこなそう

Pythonの記事一覧

Python学習カテゴリの親ページ用アイキャッチ画像(テキスト&問題集)、記事一覧へのリンク案内

次のページ>>

【Python学習記事のアイキャッチ画像】Lesson5-10 ミックスインを理解しよう

抽象クラスの疑問解消|FAQと用語のまとめ

初心者がつまずきやすいポイントをFAQとしてまとめ、またよく使う専門用語をわかりやすく整理しました。

理解を深めたいときや、ふと疑問に感じたときに役立ててください。

FAQ|抽象クラスに関するよくある質問

Q
Q1. 抽象クラスはどのようなときに使いますか?

子クラスに共通のインターフェースを強制したいときや、基盤クラスの設計を厳密にしたいときに使います。

Q
Q2. 抽象クラスとインターフェースの違いは?

Pythonには明確なインターフェース機能はありませんが、抽象クラスでインターフェースのような動作を実現できます。

Q
Q3. 抽象クラスはインスタンス化できますか?

いいえ、抽象クラスは直接インスタンス化できず、継承したサブクラスでメソッドを実装する必要があります。

Python用語集|抽象クラスに関する用語一覧

今回の記事で出てきた用語・関数などを一覧で紹介します。

このサイトに出てくる 全てのPython用語をまとめた用語集 も活用してください。

Python用語定義・使い方の概要解説記事へのリンク
抽象クラス直接インスタンス化できないクラスで、派生クラスに共通のインターフェースを定義するために使う本記事
抽象プロパティサブクラスで実装を強制するプロパティ。abc モジュールと @property を組み合わせて定義される本記事
抽象メソッドサブクラスでのオーバーライドを必須とするメソッド。基底クラスで @abstractmethod を使って宣言される本記事
abc モジュール抽象基底クラスを定義するための標準モジュール。抽象クラスや抽象メソッドの宣言に使用される本記事
継承あるクラス(親クラス)の機能を別のクラス(子クラス)が引き継ぐこと。コードの再利用を促進するLesson5-5
オーバーライド親クラスで定義されたメソッドを子クラスで再定義し、振る舞いを変更することLesson5-6
記事URLをコピーしました