🐈 【Python】オブジェクト指向学習 - 継承とコンポジション -
作成日: 2021/07/08
0

注意)このTicketはあくまで自分用のメモ。厳密な定義などは参考サイトを参照のこと

継承とコンポジションについて学ぶ

参考サイト1の動画で紹介されているTypeScriptのコードを自分なりにpythonに書き直して学習する。参考サイト1のコードはpythonにないインターフェースを利用した説明のため、今回は参考サイト3のコードの方が理解しやすい。しかし、勉強のため参考サイト1のコードを書き直したもので下記に記述する。

継承とは

pythonでの書き方

from abc import ABCMeta, abstractmethod

#インターフェース
class Arranger(metaclass=ABCMeta):

    @abstractmethod
    def arrange(self):
        pass

# 継承
class AbstractArranger(Arranger):
    def arrange(self,json):
        return self.delimiter().join(map(self.format,json))

    @abstractmethod
    def format(self,book):
        pass

    def delimiter(self):
        return "\n"

class SimpleJsonArrangerExt(AbstractArranger):
    def format(self,book):
        return book['title'] + "(" + book['author'] + ")"

#--- 動作確認 ------------------------------------
if __name__=='__main__':
    BOOKS = [{ 'title':'坊ちゃん', 'author': '夏目漱石' },\
            { 'title': '吾輩は猫である', 'author': '夏目漱石' },\
            { 'title': '友情', 'author': '武者小路実篤' },]
    
    print('### 継承版 ###')
    arranger = SimpleJsonArrangerExt()
    print(arranger.arrange(BOOKS))

実行結果

### 継承版 ###
坊ちゃん(夏目漱石)
吾輩は猫である(夏目漱石)
友情(武者小路実篤)

コンポジションとは

pythonでの書き方

from abc import ABCMeta, abstractmethod

#インターフェース
class Arranger(metaclass=ABCMeta):

    @abstractmethod
    def arrange(self):
        pass

#インターフェース
class BookFormatter(metaclass=ABCMeta):

    @abstractmethod
    def format(self):
        pass

# コンポジション
class SimpleBookFormatter(BookFormatter):
    def format(self,book):
        return book['title'] + "(" + book['author'] + ")"

class JsonArranger(Arranger):
    def __init__(self,formatter):
        self.formatter = formatter
    
    def arrange(self,json):
        return "\n".join(map(self.formatter.format,json))


#--- 動作確認 ------------------------------------
if __name__=='__main__':
    BOOKS = [{ 'title':'坊ちゃん', 'author': '夏目漱石' },\
            { 'title': '吾輩は猫である', 'author': '夏目漱石' },\
            { 'title': '友情', 'author': '武者小路実篤' },]
    
    print('### コンポジション版 ###')
    arranger = JsonArranger(SimpleBookFormatter())
    print(arranger.arrange(BOOKS))

実行結果

### コンポジション版 ###
坊ちゃん(夏目漱石)
吾輩は猫である(夏目漱石)
友情(武者小路実篤)

SimpleBookFormatterのインスタンスを渡して、JsonArrangerの中で利用しているのがポイント
JsonArrangerはSimpleBookFormatterを継承していないがインスタンスを渡すことでSimpleBookFormatterのメソッドを利用している
要はコンポジションは、継承を使わず別クラスのメソッドを利用する方法

継承とコンポジション どういったときに使う?

参考サイト2を参照。簡単にまとめると下記の通り。
「AはBである」is-a関係:継承 例.猫は動物である
「AはBを含んでいる」has-a関係:コンポジション 例.自転車はサドルを含んでいる

参考サイト1では明確なis-a関係であれば継承。曖昧な場合(継承とコンポジション両方で書ける場合)は下記利点を考えて選ぶ。悩んだときは柔軟性を重視してコンポジションで実装すると紹介していた。

[クラスの数]
★継承 < コンポジション
[構造の把握しやすさ]
コンポジション < ★継承
[クラスを実装する上での影響範囲の見えやすさ]
継承 < ★コンポジション
[柔軟性]
継承 < ★コンポジション

私の学習したイメージとしては、コンポジションは「部品」のイメージ。クラスを「部品」に分解して利用する。「部品」だから交換などがしやすい。「部品」に分解するからコード量は継承に比べると増える傾向にある。継承は親クラスを理解してコードを記述する必要があるが、「部品」はそれそのもので存在できるので、依存度が低い。

コンポジションを多用するとコードが大変になるときがあるが、ミックスインを併用すると綺麗にかけるときがある(参考サイト3を参照)。

書いたコード

github

参考サイト

  1. youtube:継承とコンポジション 【コードで理解する】 - プログラミング相談所オンライン -
  2. 継承とコンポジションをどう使い分けるか
  3. コンポジションとミックスイン【Python】
フリーランスでpythonエンジニアとして働きたく勉強中。 前職は運用SEとセキュリティエンジニア。 開発は学校で学んだ経験と趣味でやっていた程度。一応前職でも業務の自動化のためにExcel VBAやセキュリティテスト用のWebサイトの開発やセキュリティテストツールの改良などで開発はやっていた。