Python(クラス定義と継承)
Pythonでのクラス定義の仕方についてはPython(オブジェクト指向)の投稿で説明しましたので、今回は継承を用いたクラス定義についてポイントを確認していきます。
class Stack:
def __init__(self):
self._stack = []
def push(self,x):
self._stack.append(x)
def pop(self):
return self._stack.pop()
class CompleteStack(Stack):
def __init__(self):
super().__init__()
#Stack.__init__(self)
def clear(self):
self._stack.clear()
def depth(self):
return len(self._stack)
class ExStack(CompleteStack):
def __init__(self):
super().__init__()
def push(self,x,*xs):
super().push(x)
for i in xs:
super().push(i)
def pop(self,n=1):
for _ in range(n):
result = super().pop()
return result
es = ExStack()
es.push(1,2,3)
print("stack:",es._stack)
print("depth:",es.depth())
print("pop(2):",es.pop(2))
print("depth:",es.depth())
es.clear()
print("depth:",es.depth())
<プログラム実行結果>
class Stack: のように記述することでクラス定義をしていくことができますが、他のクラスの機能を拡張したクラス定義を行う場合、コピペして定義し直すのではなく、継承を用いたクラス定義を行うことで同じコードを書かなくても拡張した機能を持つクラスを定義することができます。
class CompleteStack(Stack): のようにクラス名に続いて親となるクラス名を( )内に記入し、コンストラクタ(def __init__(self):)に super().__init__() (もしくはStack.__init__(self)) と記述して親クラスの初期化を行うことで子クラスである CompleteStack でも親クラスとなる Stack の変数やメソッドを利用することができます。
さらに、 CompleteStack を継承したExStackクラスでは、Stack、 CompleteStackクラスの両方のメソッドが利用可能となります。
ExStack クラスではStackクラスで定義されたpushとpop関数を上書きしたメソッドを定義しています。この場合、子クラスのインスタンスからは子クラスのメソッドが優先されますが、super().push(x) のように記述することで、子クラスのメソッド内で親クラスのメソッドを活用することができます。
<他言語との違い>
・C++やC#のようにoverride修飾詞を記述しない
・基底クラスにvirtualをつけて仮想関数を定義する必要がない
・関数定義において引数の異なる同名関数を定義できない(オーバーロードはない)
※ただし、関数定義内に内部関数として他の関数と同名関数を定義した場合は、外からは見えない関数なので、関数名の衝突を気にせずにpythonでも同名関数を定義することができる。
(もちろん内部関数を複数作成して、それが同名の場合は定義できない。)