Developer

【Python連載】クラスの継承
2021.07.27
Lv1

【Python連載】クラスの継承

Pythonは、オブジェクト指向と呼ばれるプログラミング言語の一つです。
今回は、クラスの継承に関することに紹介します。


クラスの継承について

継承とは、既にあるクラスを元にして、新しい機能をもつクラスを定義するものです。
継承して新しくクラスを作成するとき、
・元になるクラスをスーパークラス、
・新しく作成したクラスをサブクラス
と呼びます。

ちなみに上記の呼び方以外にも、
親クラス・子クラス
基底クラス・派生クラス
などと呼ばれることもあります。

以下がスーパークラスを持つサブクラスの書式となります。

class サブクラス名(スーパークラス名):
        ステートメント                                      #ステートメントに処理を記述
           ・・・

さて、スーパークラスを元に実際にサブクラスを定義していくわけですが・・・
何のために継承を行うのか、ピンと来ませんよね?

継承のメリットとしては、まずコードの再利用性があります。
スーパークラスの構造と機能は、サブクラスに引き継がれます。一つのスーパークラスからサブクラスをいくつも作成した場合でも、同じように引き継がれます。各サブクラスに共通するような構造や機能はスーパークラスで定義しておけば、冗長なコードを各サブクラスに記載する必要はなくなるということです。
また、上記のコード再利用性にばかり目を向けられがちですが、、、
継承において、各サブクラスではスーパークラスで定義したメソッドを利用出来るだけではなく上書きも可能であり(『オーバーライド』といい、次回の記事で詳しく説明します)、またスーパークラスにはない独自のメソッドも定義も可能であるため、自由に機能を拡張できることも継承のメリットです。

とはいえ具体例を見てみないとイメージが難しいと思いますので、実際に見てみましょう。

継承の例としては、Personクラスというものを作成してみます。

まずは、以下を見てみましょう。

#クラスの定義
class Person():
    def __init__(self,name,age): #初期化メソッド
        self.name = name
        self.age = age
    
    def my_introduction(self):  #インスタンスメソッド
        print(f"名前は{self.name}、年齢は{self.age}です")

#Personクラスからインスタンスを作成し、メソッドを実行
person1 = Person("Taro",15)
person1.my_introduction()
C:\Python> python 13-5-2.py
名前はTaro、年齢は15です

Personクラスというものを定義しました。
インスタンスを作成する際に、初期化メソッドでnameとageを属性として持てるようにしています。
また、print文での簡単な自己紹介のようなメソッドも定義しています。

では、今回はPersonクラスをスーパークラスとして、StudentクラスとTeacherクラスを作成してみます。
Personというのは、『人』というような意味ですよね。名前や年齢などの属性があると思います。
その『人』をベースにして、『Student(生徒)』や『Teacher(先生)』といったものを定義する設計図を作成する、というイメージになります。

#スーパークラスの定義
class Person():
    def __init__(self,name,age): #初期化メソッド
        self.name = name
        self.age = age
    
    def my_introduction(self):  #インスタンスメソッド
        print(f"名前は{self.name}、年齢は{self.age}です")

#サブクラスの定義その1
class Student(Person):
    def __init__(self,name,age,standard_score = 50): #スーパークラスには無いstandard_scoreという属性を持つ
        self.name = name
        self.age = age
        self.standard_score = standard_score

    def study(self):    #Studentクラス独自のメソッドを定義
        self.standard_score += 1
        print(f"勉強をします。偏差値が{self.standard_score}に上がりました。")

#サブクラスの定義その2
class Teacher(Person):
    def __init__(self,name,age,subject): #スーパークラスには無いsubjectという属性を持つ
        self.name = name
        self.age = age
        self.subject = subject

サブクラス特有の属性として、
Studentクラスでは新たにstandard_score(偏差値)という属性を、
Teacherクラスでは新たにsubject(授業科目)という属性を持てるようにしました。

また、Studentクラスでは、スーパークラスには無い独自のメソッドを定義してみました。
せっかくですので、Studentクラスをインスタンス化してみて、メソッドを実行してみます。

#---クラス部分記載省略---

Student1 = Student("Taro",15) #サブクラスからインスタンスを作成し、メソッドを実行
Student1.study()
C:\Python> python 13-5-4.py
勉強をします。偏差値が51に上がりました。

このようにサブクラスでは独自のメソッドを定義することも出来ますが、
もちろん、スーパークラスのメソッドをそのまま使用することも出来ます。

#---クラス部分記載省略---

Teacher1 = Teacher("Sato",40,"English") #サブクラスからインスタンスを作成し、スーパークラスのメソッドを実行
Teacher1.my_introduction()
C:\Python> python 13-5-5.py
名前はSato、年齢は40です

名前と年齢しか自己紹介されておらず、せっかくTeacherクラスのインスタンスにはsubject(授業科目)という属性が追加されたのに、もったいないですね。
各クラスに新しくメソッドを定義しても良いのですが・・・実は、オーバーライドという方法で、スマートに解決することが出来ます。
次回の記事で、詳しく説明していきます。


まとめ

・継承とは、既にあるクラスを元にして新しい機能をもつクラスを定義すること
・元になるクラスをスーパークラス(親クラス、基底クラス)、新しく作成したクラスをサブクラス(子クラス、派生クラス)と呼ぶ


確認問題

次のようなプログラムがあります。

class Person():
    def __init__(self,name,age):
        self.name = name
        self.age = age

    def my_introduction(self):
        print(f"名前は{self.name}、年齢は{self.age}です")

class Student():
    def __init__(self,name,age,standard_score = 50):
        self.name = name
        self.age = age
        self.standard_score = standard_score

Student1 = Student("Taro",15)
Student1.my_introduction()

このプログラムを実行すると、以下のようなエラーが発生します。

line 17, in <module>
Student1.my_introduction()

AttributeError: ‘Student’ object has no attribute ‘my_introduction’

このエラーの原因を考えてみましょう。

答えは次回の記事の最後に!
【Python連載】メソッドのオーバーライド