ヌルポインター親衛隊

社内でひとりエンジニアやってます。

Python学習3日め(オブジェクト指向基礎)

今日までにブログを見ていて、煩雑な文章だなぁと思う。たぶん、誰かの役に立つための文章を目指していないからだろう。でも、とにかく今はどういう形でも良いからアウトプットする習慣を付けたいので、「役に立つ」ことより「書くこと」に重点を置きたいと思う。

さて、私は学校でC言語を学んだ経験から、手続き型のパラダイムは少しながら理解している。しかしながら、より効率的で大規模なプロジェクトに向いているオブジェクト指向型のパラダイムは未学習に等しい。Pythonの勉強をはじめて3日目でようやく2部に入り、オブジェクト指向の基礎を学んだ。

オブジェクト指向とは

プログラミングパラダイム(方法論、考え方)のうちの一つであるオブジェクト指向型は、プログラムの状態をオブジェクトとして管理する手法。オブジェクトはクラスと呼ばれる設計図のようなものから生成され、これを~クラスのインスタンスオブジェクトと呼ぶ。
オブジェクト指向には重要な概念がいくつかあるので、以下に示す。

カプセル化

オブジェクトに、複数の状態を持たせる、及び状態を変更する方法をもたせること。それぞれインスタンス変数とメソッドと呼ぶ。インスタンス変数はクラスの外部から参照することはできない。
次に示すコードは、Dataというclassである。

class Data:
    def __init__(self):
        self.nums = [1, 2, 3, 4, 5]
        
    def change_data(self, index, n):
        self.nums[index] = n

このクラスのインスタンス変数であるnumsにアクセスするには、2通りの方法がある。

data1 = Data()
data1.nums[0] = 100 #良くない
data1.change_data(3, 20) #良い

2行目の「#良くない」は、インスタンス変数に直接アクセスして書き換えているから良くない、らしい...。しかし、Pythonは変数にprivate/publicの状態を持たせることができないらしく、いつでもこのようなアクセスが可能となる。先頭文字をアンダースコアにして明示することは可能であるが、それでも外部からアクセスできてしまう。
そこで、この問題を解決するのが「#良い」のようにメソッドを介したインスタンス変数の操作。・・・という認識で合っているのだろうか。こんな感じなのがカプセル化

抽象化

抽象化は、細かい部分を排して、本質的な部分だけを集めた状態にすること。

ポリモーフィズム

次のコードを見てほしい。

print("hello, world!")
print(1)
print(["YAMAHA", "HONDA", "KTM"])

この3つのprint()は、それぞれの引数がstrクラス、intクラス、listクラスであるが、出力は全て標準出力である。全く違ったデータ型であっても同じ動作をするインターフェース(関数/メソッド)を提供するのが、ポリモーフィズムの考え方である。

継承

文字通りの意味で、親クラスの機能を受け継ぐことができる。例えば次のようなコードでは、子クラスCb400は親クラスHondaの理念(believe)の"Dreams"を受け継いでいる。

class Honda:
    def __init(self)__:
        self.believe = "Dreams"

class Cb400(Honda):
    def __init(self)__:
        pass

『has-a』関係

上のコードを少し改良して、Cb400にオーナー情報をもたせてみる。

class Honda:
    def __init(self)__:
        self.believe = "Dreams"

class Person:
    def __init(self, name)__:
        self.name = name

    def print_name(self):
        print(self.name)

class Cb400(Honda):
    def __init(self, owner)__:
        self.owner = owner

こうすることで、PersonクラスのインスタンスCb400クラスのインスタンスとの間にhas-aの関係が生じる。つまり主従関係。この場合、Cb400クラスのインスタンス変数ownerのデータ型はPerson型であるので、以下のようなコードが書ける。

hiroshi = Person("山田 ひろし")
hiroshis_cb400 = Cb400(hiroshi)

hiroshis_cb400.owner.print_name()

オブジェクト指向しゅごい。

おわりに

クラスってすごいな、と思った一日でした。しかしながら、継承や、has-aの関係があるということは、プログラムが大規模になってきた時に返って分かりづらくなる気がします。そのためにカプセル化という概念がある感じでしょうか。

本日は独学プログラマー12章と13章をやりました。