29. Inheritance mendalam

Bab 27 menyinggung inheritance: satu class membangun dari class lain. Ini adalah cara menghindari penulisan kode yang sama dua kali. Seekor Dog dan seekor Cat keduanya adalah Animal — nama yang sama, cara dideskripsikan yang sama, hanya berbeda pada suara yang dibuatnya. Inheritance menulis bagian yang sama sekali saja.

Class dasar

Mulai dengan class umum. Semua yang sama dalam satu keluarga ada di sini:

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

    def describe(self):
        print(f"{self.name} is an animal.")

Class anak yang mewarisi

Sebutkan parent dalam tanda kurung, lalu panggil super().__init__() untuk menjalankan constructor parent:

class Dog(Animal):
    def __init__(self, name):
        super().__init__(name)   # run Animal's __init__

Dog tidak memiliki describe-nya sendiri, tapi ia mewarisi dari Animal, sehingga instance Dog menemukannya di sana:

rex = Dog("Rex")
rex.describe()    # Rex is an animal.   (inherited from Animal)

Python mencari describe di rex, tidak menemukannya, lalu memeriksa Dog, tidak menemukannya di sana juga, dan akhirnya menemukannya di Animal.

Menambah perilaku yang hanya dimiliki anak

Berikan method pada anak yang tidak dimiliki parent. Method-method itu didefinisikan pada class anak, tidak terlihat oleh parent dan class saudara:

class Dog(Animal):
    def __init__(self, name):
        super().__init__(name)

    def fetch(self):
        print(f"{self.name} fetches the ball.")

rex = Dog("Rex")
rex.fetch()       # Rex fetches the ball.

Overriding: mengganti method parent

Jika anak mendefinisikan method dengan nama yang sama seperti milik parent, versi anak ditemukan lebih dulu dan menang — ini disebut overriding:

class Dog(Animal):
    def __init__(self, name):
        super().__init__(name)

    def describe(self):
        print(f"{self.name} is a dog.")

rex = Dog("Rex")
rex.describe()    # Rex is a dog.   (Dog's version, not Animal's)

Sekarang Python menemukan describe di Dog dan tidak pernah melihat ke Animal.

Memanggil versi parent juga

Kadang kamu ingin memperluas method parent, bukan menggantinya: lakukan apa yang dilakukannya, lalu tambahkan sesuatu. Gunakan super() untuk memanggil versi parent:

class Dog(Animal):
    def __init__(self, name):
        super().__init__(name)

    def describe(self):
        super().describe()                   # do the Animal part first
        print("  ...specifically, a dog.")   # then the Dog part

rex = Dog("Rex")
rex.describe()
# Rex is an animal.
#   ...specifically, a dog.

super().describe() menjalankan Animal.describe pada instance ini, kemudian baris khusus Dog mengikuti. "Memanggil ke parent" ini adalah salah satu alat paling berguna dalam kode object-oriented.

Buka exercises/29/01-animals.py. Di sana ada Animal dan Dog. Tambahkan Cat yang mewarisi dari Animal, mengesampingkan describe untuk mengatakan bahwa ia adalah kucing, dan menambahkan method meow. Buat satu kucing dan panggil keduanya.

Memeriksa tipe dengan isinstance

isinstance(obj, ClassName) mengembalikan True jika obj adalah instance dari class itu atau subclass mana pun:

rex = Dog("Rex")
print(isinstance(rex, Dog))      # True
print(isinstance(rex, Animal))   # True  (Dog is a subclass of Animal)

Ini memungkinkanmu menulis kode yang berperilaku berbeda tergantung pada jenis object yang diterimanya.

Pekerjaan Rumah

File pekerjaan rumah ada di exercises/29/homework/.

Soal 1 — Vehicle dan Car

Buka exercises/29/homework/01-vehicle.py. Buat class dasar Vehicle dengan __init__(name) dan describe() yang mencetak <name> is a vehicle.. Kemudian buat Car yang mewarisi darinya. Buat sebuah car dan panggil describe() — ia harus menggunakan method yang diwariskan.

Soal 2 — Override

Buka exercises/29/homework/02-override.py. Dari class Vehicle/Car, override describe() pada Car untuk mencetak <name> is a car. sebagai gantinya. Pastikan Vehicle masih mengatakan "vehicle" dan Car mengatakan "car".

Soal 3 — Memperluas parent

Buka exercises/29/homework/03-extend.py. Override Car.describe() agar pertama-tama memanggil super().describe(), lalu mencetak baris tambahan, It has four wheels.. Kedua baris harus muncul.

Tantangan — Dua anak

Buka exercises/29/homework/04-two-children.py. Buat Animal ditambah dua anak, Bird dan Fish. Masing-masing meng-override move() untuk mencetak cara bergeraknya (flies, swims). Buat satu dari masing-masing, masukkan ke dalam list, dan loop ke seluruhnya sambil memanggil move().

Buntu atau sudah selesai? Buka halaman solusi pekerjaan rumah.