本記事は「速習 Python3 オブジェクト指向編」で学んだ内容のうち、プログラミングを書く際に意識することと本書から学べなかったことをまとめました。
この記事は完全に私の備忘録なので、書きたいことを箇条書きで書いていくだけです。粒度もそろっていませんし、順不同です。あまり人の役に立たない記事であることをあらかじめお詫びしておきます。
意識すること
- データ構造を意識して設計する。要点は下記3点。
- who:誰がデータを持つのか?
- what:どんなデータを持つのか?
- how:どのように持つのか?
- 「クラス = 構造体(型を指定した変数を複数持っている構造)+ メソッド」ととりあえず理解する。
例えば、下記の場合クラスExampleの構造体は、a, b、メソッドは__init__とfunc1と理解している。
class Example: def __init__(self, a, b): self.a = a self.b = b def func1(self): print(self.a, self.b)
- メソッドは、そのクラスが持つデータを操作するような処理に使う。(つまり、クラスの外で定義されたグローバル変数をクラスの中で処理しない)
- インスタンス生成直後にインスタンス変数を初期化すべきときは、コンストラクタ内で初期化する。
- 文法的な制約ではなく、可読性の観点からそうすべきとのこと。
- メソッドや変数は何をクラスの外に見せて、何を外に見せないかきっちり決めて設計する。
- クラス間のやり取りはツリー構造にすべき。
例えば、下記クラスにおいてclass B, C間で変数のやり取りがあると複雑になってしまい、設計が難しくなる。
- 「AがBのインスタンスを持つ」というスタイルでできるだけ設計する。
継承を避けるべきとのこと。例えば、クラスExample1の変数やメソッドをクラスExample2で使おうと思ったら、下記のように実装すべきとのこと。
class Example1: def __init__(self, a): self.a = a class Example2: def __init__(self, ex1): self.ex1 = Example1(a=1)
ただ、継承を避けるべき理由が私はよくわかっていない。下記を見ると、「基底クラスと派生クラスの役割(責務)の分担が非常に難しい」と書かれているが、その感覚がイマイチわからぬ...。 jp.quora.com まあ、今後クラス設計の経験をたくさん積んでいけば、わかるようになるでしょうということで一旦放置。
- クラス間のやりとりをする場合は、呼び出し側のクラスにも呼び出される側のクラスにもメソッドが必要。
- 継承がどうしても必要なときは、呼び出されるメソッドは親クラスに書く。つまり、子クラスではメソッドの内部を変更するくらいにとどめて、新規に新しいメソッドを作らない。
- グローバル変数は参照するだけにして、書き換えない。
- クラスやメソッドを定義するときは、ドキュメントを必ず記載する。
残件(学べなかったこと)
- 設計方法はほとんど学べなかった
- クラス単位で処理すべきものと、メソッド単位で処理すべきものの違いは何か?
- クラスはどうやって分ける?