継承

Python SELF JA
レベル 15 , レッスン 6
使用可能

6.1 継承は簡単

継承はオブジェクト指向プログラミング (OOP) の基本概念の1つで、1つのクラス (子クラスまたはサブクラスと呼ばれる) が、他のクラス (親クラスまたはスーパークラスと呼ばれる) のフィールドやメソッドを継承することを可能にするんだ。

こうすることで、より汎用的なクラスを作成したり、コードを再利用しやすくなり、コードの組織化と保守性が向上するよ。

継承を使う理由は?

例えば、クラスで何かコードを書こうとしているときに、既にプロジェクトに似たようなことをするクラスがあることを知ったとする。コードをコピーして自分のクラスで使うこともできるけど、本当のコピーじゃなくて、「コピーみたいなこと」をすることもできるよ。クラスを子クラスとして宣言すると、Pythonが親クラスの動作をそのクラスに追加してくれるんだ。

自然界の一部だと思って、犬を作りたいと思ってみて。細菌から10億年かけて犬を作るのと、2万年かけてオオカミを家畜化するの、どっちが早いかな?

基本的な継承の例

例えば、親クラスAnimalがあって、フィールドnameがあるとする:


class Animal:
    def __init__(self, name):
        self.name = name

これに対して、2つの子クラスDogCatを作成し、それぞれにメソッドspeakを追加したい:


class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"

class Cat(Animal):
    def speak(self):
        return f"{self.name} says Meow!"

上記の例では、子クラスDogCatAnimalを継承し、メソッドspeakを追加しているんだ。

クラスDog:

  • Animalからname属性を継承する。
  • 犬特有の文字列を返すメソッドspeakを追加する。

クラスCat:

  • Animalからname属性を継承する。
  • 猫特有の文字列を返すメソッドspeakを追加する。

完成したコードは次のようになるよ:


class Animal:
    def __init__(self, name):
        self.name = name
         
class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"
        
class Cat(Animal):
    def speak(self):
        return f"{self.name} says Meow!"
         
dog = Dog("Buddy")
cat = Cat("Whiskers")
        
print(dog.speak())  # 出力: Buddy says Woof!
print(cat.speak())  # 出力: Whiskers says Meow!

この例では、Animalは親クラスで、DogCatは子クラスだね。子クラスは親クラスAnimalからname属性と__init__メソッドを継承しているけど、speakというメソッドも追加しているよ。

6.2 継承の裏側

クラスに親クラスを追加すると、親クラスのコードが自分のクラスにコピーされたように思えることがあるよ。


class Animal:
    def __init__(self, name):
        self.name = name
         

class Dog(Animal):
    def __init__(self, name):
        super().__init__(name)  # 親クラスのコンストラクタを呼び出す
        
    def speak(self):
        return f"{self.name} says Woof!"
        
class Cat(Animal):
    def __init__(self, name):
        super().__init__(name)  # 親クラスのコンストラクタを呼び出す
        
    def speak(self):
        return f"{self.name} says Meow!"
        

dog = Dog("Buddy")
cat = Cat("Whiskers")
        
print(dog.speak())  # 出力: Buddy says Woof!
print(cat.speak())  # 出力: Whiskers says Meow!

これは厳密に言うと正確な説明ではないけれど、もし継承の概念を初めて聞くなら、しばらくこのくらいに考えておいてもいいよ。後で詳細を追加するからね。

6.3 継承の階層

複雑なクラスの大規模なグループを設計する際、継承の階層全体と向き合うことがあるかもしれない。

例えば、Animalクラスがあるとすると、これはすべての動物の基底クラスだね:


class Animal:
    def __init__(self, name):
        self.name = name
        
    def speak(self):
        raise NotImplementedError("Subclass must implement abstract method")

さらにメソッドspeakを追加してるけど、抽象的な動物は話さないから、このメソッドはNotImplementedError例外を投げているよ。それが標準のやり方なんだ。

次に、動物のカテゴリに対応する中間クラスを追加してみると: Mammalは哺乳類で、Birdは鳥類。


class Mammal(Animal):
    def __init__(self, name, fur_color):
        super().__init__(name)  # 親クラスのコンストラクタを呼び出す
        self.fur_color = fur_color
         

class Bird(Animal):
    def __init__(self, name, wing_span):
        super().__init__(name)  # 親クラスのコンストラクタを呼び出す
        self.wing_span = wing_span
        
    def fly(self):
        return f"{self.name} is flying with a wingspan of {self.wing_span} meters."

最後に、具体的な動物種のクラスが最終段階で現れるんだ:


class Dog(Mammal):
    def speak(self):
        return f"{self.name} says Woof!"
         
        
class Cat(Mammal):
    def speak(self):
        return f"{self.name} says Meow!"
        
class Parrot(Bird):
    def speak(self):
        return f"{self.name} says Squawk!"

通常、最終コードはこれらと一緒に動作するよ:


animals = [Dog("Buddy", "brown"), Cat("Whiskers", "white"), Parrot("Polly", 0.5)]
            
for animal in animals:
    print(animal.speak())

print(f"{dog.name} has {dog.fur_color} fur.")  # 出力: Buddy has brown fur.
print(f"{cat.name} has {cat.fur_color} fur.")  # 出力: Whiskers has white fur.
print(parrot.fly())  # 出力: Polly is flying with a wingspan of 0.5 meters.

技術的には、数十の祖先を持つ階層を作成することに制限はないけれど、必要がない場合はシンプルさを維持するほうが良い。シンプルさの中に力があるんだよ。

1
Опрос
クラスとオブジェクト指向,  15 уровень,  6 лекция
недоступен
クラスとオブジェクト指向
クラスとオブジェクト指向
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION