0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonの抽象クラスについて勉強してみた

Posted at

概要

Java, Python等のオブジェクト指向言語を扱っていると避けて通れないのがクラスという概念
今回は抽象クラスについてまとめていこうと思います

記事の対象者

  • 抽象クラスを知らない人
  • オブジェクト指向について勉強中の人

抽象クラスとは?

具体的な実装を持たないメソッドを一つ以上含むクラスのこと のようです
抽象クラスはIS Aの関係であるため親クラスでできることはもちろん子供クラスでもできます

抽象クラスが存在する意味

  • 複数のクラスで共通してもつべきメソッドの「形」を定義することで、コードの統一性と保守性を高めます
  • 子クラスは、抽象クラスの抽象メソッドを必ず実装しなければならないため、これにより、子クラスが最低限備えるべき機能を保証できる

抽象クラスのメリット

  • 共通の機能を抽象クラスにまとめることで、コードの重複を減らし、保守性を向上できる
  • システム全体の構造を明確にし、開発チーム間の共通理解を促進できる
  • 抽象クラスを基底クラスとすることで、多様なオブジェクトを統一的に扱うことができる

実装例

図形の面積を計算するパターンで考えます

抽象クラス

抽象メソッドにはデコレータを指定します
calc_surface_areaの抽象メソッドをもつ、図形抽象クラスができました

shape.py
import abc

class Shapes(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def calc_surface_area(self) -> int:
        # pass を使うよりもこちらのほうが妥当
        raise NotImplementedError()

実装クラス

では、図形抽象クラスを継承する実装クラスを考えます
一番下に図形抽象クラスを継承していないが、同じメソッド名をもつDiamondクラスがありますが、これは次のユースケースで説明します

shape.py
import math

# 実装クラス
class Square(Shapes):
    def __init__(self, width: int, height: int):
        self.width = width
        self.height = height

    def calc_surface_area(self) -> int:
        return self.width * self.height


# 実装クラス
class Circle(Shapes):
    def __init__(self, radius: float):
        self.radius = radius

    def calc_surface_area(self) -> float:
        return math.pi * self.radius * self.radius

class Diamond:
    def __init__(self, width: float, height: float):
        self.width = width
        self.height = height

    def calc_surface_area(self) -> float:
        return self.width * self.height / 2

ユースケース

実際の現場では同じメソッド名をもつが特定の抽象クラスを継承している場合のみ、メソッドを実行したい場合があると思います
以下のように型を判定をするだけで、図形抽象クラスを継承しているsquareとcircleのみがcalc_surface_area()を実行することができます

main.py
from shape import Shapes, Circle, Square, Diamond

if __name__ == '__main__':
    square = Square(width=5, height=5)
    circle = Circle(radius=12)
    diamond = Diamond(width=10, height=5)

    shapes = [square, circle, diamond]
    for shape in shapes:
        # 型がShapesであるかどうかだけを判断している -> 分岐を削減することができる
        if isinstance(shape, Shapes):
            print(shape.calc_surface_area())
        else:
            # diamondはShapesを継承するクラスではないので、elseに入る
            print(shape.__class__.__name__)
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?