Python入門 - 継承と包含 使い方編
継承の使い方
前回の記事で、継承の考え方を説明してきました。
その継承の考え方を、Pythonではどのように実現しているかをみていきましょう。
継承には、スーパークラスとサブクラスの2種類のクラスが登場します。
スーパークラスには、特別な作り方はなく、普通にクラスを作成すれば大丈夫です。
サブクラスでは、どのクラスを継承するかを指定する必要があります。
書式
class サブクラス名(スーパークラス名):
サブクラスのメンバ変数やメソッッド
サブクラスのメンバ変数やメソッッド
・・・
サンプルコード
class Animal:
def __init__(self, name):
self.name = name
def eat(self, food):
print('Animal:' + self.name + ' eat ' + food)
class Bird(Animal):
def fly(self):
print(self.name + ' Flies!')
class Human(Animal):
def useFire(self):
print(self.name + ' Uses fire!')
swallow = Bird('swallow')
swallow.eat('warm')
swallow.fly()
someone = Human('someone')
someone.eat('beef')
someone.useFire()
実行結果
Animal:swallow eat warm
swallow Flies!
Animal:someone eat beef
someone Uses fire!
継承の仕方はとても簡単ですね。サブクラス名の後ろにかっこでスーパークラス名を書くだけです。
BirdとHumanはどちらもAnimalを継承しています。そのため、スーパークラスであるAnimalのメソッドであるeatをBirdのオブジェクトもHumanのオブジェクトも使うことができます。メンバ変数やコンストラクタも同様で、Animalのメンバ変数nameやコンストラクタを利用できます。
また、Birdのflyメソッドのようにサブクラス独自のメソッドやメンバ変数も追加できます。
オーバーライド
前のサンプルでは、スーパークラスのメソッドをそのまま利用しました。
しかし、実際にはスーパークラスのメソッドに、サブクラス独自の改造を加えたい場合もあります。そのようたとき、メソッドの「オーバーライド」をすることができます。スーパークラスのメソッドをサブクラスで「上書き」するということです。オーバーライドするには、「サプクラスでオーバーライドしたいメソッド」を「スーパークラスと同じメソッド名で定義」します。
サンプルコード
class Animal:
def __init__(self, name):
self.name = name
def eat(self, food):
print('Animal:' + self.name + ' eat ' + food)
class Bird(Animal):
def eat(self, food):
print('Bird:' + self.name + ' eat ' + food)
def fly(self):
print(self.name + ' Flies!')
class Human(Animal):
def eat(self, food):
print('Human:' + self.name + ' eat ' + food)
def useFire(self):
print(self.name + ' Uses fire!')
swallow = Bird('swallow')
swallow.eat('warm')
swallow.fly()
someone = Human('someone')
someone.eat('beef')
someone.useFire()
実行結果
Bird:swallow eat warm
swallow Flies!
Human:someone eat beef
someone Uses fire!
継承時の__init__
サブクラスに、「サブクラス独自のメンバ変数を追加したい」とか「最初に設定する値を変更したい」時にどうしたらいいかを説明したいと思います。
やり方は簡単で、スーパークラスのコンストラクタを呼び出したあとで、サブクラスで独自にやりたいことを追加するだけです。
サンプルコード
class Animal:
def __init__(self, name):
self.name = name
def eat(self, food):
print('Animal:' + self.name + ' eat ' + food)
def printName(self):
print('Name: ' + self.name)
class Human(Animal):
def __init__(self, name, age):
Animal.__init__(self, name)
self.name = 'Human:' + name
self.age = age
def eat(self, food):
print('Human:' + self.name + ' eat ' + food)
def useFire(self):
print(self.name + ' Uses fire!')
def printAge(self):
print(self.age)
someone = Human('someone', 20)
someone.printName()
someone.printAge()
実行結果
Name: Human:someone
20
isinstance
プログラミング言語的には、クラスを作るというのは、オリジナルのデータ型を定義することになります。あるオブジェクトが、どのデータ型のものなのかを確認する方法に「isinstance」があります。
たくさんクラスを作っていくと、クラスの種類(データ型の違い)によって処理を分けたりしたい場合も出てくるかもしれません。そういった時に「isinstance」を使います。
サンプルコード
class Animal:
def __init__(self, name):
self.name = name
def eat(self, food):
print('Animal:' + self.name + ' eat ' + food)
def printName(self):
print('Name: ' + self.name)
class Bird(Animal):
def eat(self, food):
print('Bird:' + self.name + ' eat ' + food)
def fly(self):
print(self.name + ' Flies!')
class Human(Animal):
def __init__(self, name, age):
Animal.__init__(self, name)
self.name = 'Human:' + name
self.age = age
def eat(self, food):
print('Human:' + self.name + ' eat ' + food)
def useFire(self):
print(self.name + ' Uses fire!')
def printAge(self):
print(self.age)
someone = Human('someone', 20)
animal = Animal('animal')
bird = Bird('bird')
print(isinstance(someone, Human))
print(isinstance(someone, Animal))
print(isinstance(Animal, Human))
print(isinstance(bird, Animal))
print(isinstance(bird, Human))
print(isinstance(1, int))
print(isinstance(123.45, float))
print(isinstance([1, 2, 3], list))
print(isinstance((1, 2, 3), tuple))
実行結果
True
True
False
True
False
True
True
True
True
someoneはHumanクラスのインスタンスです。さらに、Human is a Animalなので、someoneはAnimalでもあります。birdはAnimalですが、Humanではありません。isinstanceは「is-a」関係をそのまま表現した関数です。
包含の使い方
継承と違い、包含には包含をするための特別な文法というものはありません。単純に、あるクラスを別のクラスのメンバ変数にするだけでOKです。
実のところ、実際のプログラムでは継承よりも包含の方がよく使うと思います。継承か包含か迷うようであれば、包含にしましょう。