Python のクラス定義
Python のクラス定義
ここでは Python でクラスを定義するときの基本的な書き方について、ざっと見ていきましょう。
まずクラスを定義するときには、class キーワードを用いて、明示的に行います。
コンストラクタは __init__ メソッドとして定義します。第一引数が self で、それぞれのインスタンスをさします。 (Java や C++ の this のようなものです) 第二引数からユーザー定義のパラメータが来ます。デフォルトの値がある場合は、=<値> で指定します。
class Person:
def __init__(self, name, age):
print('[Person.__init__]')
self.name = name
self.age = age
def show_info(self):
print('[Person.show_info]')
print('%s (%d)' % (self.name, self.age))
上の例では、Person という名前のクラスを定義して、コンストラクタで name と age という二つの引数を受けとることを定義しました。
そして、その中で print でトレースを出力してから、self.name と self.age に値を設定します。 インスタンスの属性を設定するのは、このように self.属性名 という形で設定します。
show_info というメソッドでは、name と age という二つの属性にセットされた値を print で出力しています。
では、この Person クラスを使うコードを見てみましょう。
上のコードを person.py というファイル (モジュール) に保存しているとします。そうすると from ... import は以下のようになります。
from person import Person
p1 = Person('Ichiro Suzuki', 37)
p2 = Person('Hanako Yamada', 35)
p1.show_info()
p2.show_info()
インスタンスを生成するのは、クラス名と同じ名前のメソッドです。(他のオブジェクト指向言語でよくみる new キーワードは使いません)
実行結果は次の通りです。
[Person.__init__]
[Person.__init__]
[Person.show_info]
Ichiro Suzuki (37)
[Person.show_info]
Hanako Yamada (35)
確かにコンストラクタ (__init__メソッド) も呼ばれており、また、それぞれのインスタンス毎に別々の値を持っていることも分かりますね。
Python でのクラスの継承
続いて継承です。Person クラスを継承して、Employee クラスを定義しましょう。
当然、「従業員 (Employee) は人 (Person) 」という関係があるとき、Person を親クラスにして、Employee を派生します。
オブジェクト指向プログラミングでは、このような関係の時 「"is-a" の関係がある」という言い方をするときもあります。
Person クラスを継承し (引き継ぎ)、Employee クラスを定義することで、Person としての機能を全て維持したまま、新しい機能を追加することができます。
Employee クラスで追加したのは company という属性です。コンストラクタで受け取って、それを属性に保持しましょう。
Employee クラスは次のように実装できます。
from person import Person
class Employee(Person):
def __init__(self, name, age, company):
print('[Employee.__init__]')
Person.__init__(self, name, age)
self.company = company
まず、親クラスは クラス名 (親クラス名) として指定します。今、クラス名は Employee、親クラスは Person ですから class Employee(Person) となります。
そして、親クラスのコンストラクタを呼ぶのは クラス名.__init__ という形で呼び出します。 ここでは Employee.__init__ 内で Person.__init__ を呼び出し、name と age を保存しています。
company は Employee クラスで新しく登場したフィールドなので、 ここで self.company = company としてここで保存しています。
さて、では動作確認をしましょう。
from employee import Employee
p = Employee('Hanako Yamada', 35, 'Ace Company')
p.show_info()
実行結果は次の通りです。
[Employee.__init__] # Employee のコンストラクタ
[Person.__init__] # Person のコンストラクタ
[Person.show_info] # show_info メソッドが呼ばれた
Hanako Yamada (35)
トレースの結果、Employee, Person 両方のコンストラクタが呼ばれていることがわかります。
また、Employee のオブジェクトから Person クラスの show_info メソッドが呼ばれていることがわかります。確かに Person が継承されています。
Python のメソッドのオーバーライド
上で見たように、Employee クラスでは確かに Person クラスで定義した show_info メソッドが確かに使えました。
しかし、Person クラスの show_info メソッドでは、Employee クラスで新しく追加した company というフィールドを表示できません。
そこで、Employee クラスで新たに show_info メソッドを上書きして、 company も表示しましょう。
このように、親クラスのメソッドを継承したクラスで新しく定義し直すことを、メソッドのオーバーライドといいます。
from person import Person
class Employee(Person):
def __init__(self, name, age, company):
print('[Employee.__init__]')
Person.__init__(self, name, age)
self.company = company
def show_info(self):
print('[Employee.show_info]')
print('%s (%d) %s' % (self.name, self.age, self.company))
Employee クラスをこのように書き換えます。10-12行目で show_info メソッドをオーバーライドしています。
再度、上のプログラムを実行してみましょう。
[Employee.__init__]
[Person.__init__]
[Employee.show_info]
Hanako Yamada (35) Ace Company
今度は確かに会社名 (company Ace Company) も表示されています。
以上で、Python でのクラス定義、クラスの継承、メソッドのオーバーライドを行う方法を説明しました。