Warisan dan Polimorfisme
Warisan dan polimorfisme - ini adalah konsep yang sangat penting dalam Python. Anda harus memahaminya dengan lebih baik jika ingin belajar.
Warisan
Salah satu keuntungan utama dari Pemrograman Berorientasi Objek adalah penggunaan kembali. Pewarisan merupakan salah satu mekanisme untuk mencapai hal yang sama. Inheritance memungkinkan programmer untuk membuat kelas umum atau dasar terlebih dahulu dan kemudian memperluasnya ke kelas yang lebih khusus. Ini memungkinkan programmer untuk menulis kode yang lebih baik.
Menggunakan pewarisan, Anda dapat menggunakan atau mewarisi semua bidang data dan metode yang tersedia di kelas dasar Anda. Nanti Anda dapat menambahkan metode dan bidang data Anda sendiri, sehingga warisan menyediakan cara untuk mengatur kode, daripada menulis ulang dari awal.
Dalam terminologi berorientasi objek ketika kelas X memperluas kelas Y, maka Y disebut kelas super / induk / basis dan X disebut kelas subkelas / anak / turunan. Satu hal yang perlu diperhatikan di sini adalah bahwa hanya bidang data dan metode yang tidak privat yang dapat diakses oleh kelas anak. Bidang dan metode data pribadi hanya dapat diakses di dalam kelas.
sintaks untuk membuat kelas turunan adalah -
class BaseClass:
Body of base class
class DerivedClass(BaseClass):
Body of derived class
Mewarisi Atribut
Sekarang lihat contoh di bawah ini -
Keluaran
Kami pertama kali membuat kelas yang disebut Tanggal dan meneruskan objek sebagai argumen, di sini-objek adalah kelas bawaan yang disediakan oleh Python. Kemudian kami membuat kelas lain yang disebut waktu dan menyebut kelas Tanggal sebagai argumen. Melalui panggilan ini kita mendapatkan akses ke semua data dan atribut kelas Tanggal ke dalam kelas Waktu. Karena itu ketika kita mencoba mendapatkan metode get_date dari objek kelas Time tm yang mungkin kita buat sebelumnya.
Object.Attribute Lookup Hierarchy
- Contoh
- Kelas
- Semua kelas yang mewarisi kelas ini
Contoh Warisan
Mari kita lihat penutupan ke dalam contoh warisan -
Mari buat beberapa kelas untuk berpartisipasi dalam contoh -
- Hewan - Kelas mensimulasikan hewan
- Kucing - Subkelas Hewan
- Anjing - Subkelas Hewan
Di Python, konstruktor kelas digunakan untuk membuat objek (instance), dan menetapkan nilai untuk atributnya.
Pembuat subclass selalu dipanggil ke konstruktor kelas induk untuk menginisialisasi nilai atribut di kelas induk, kemudian mulai menetapkan nilai untuk atributnya.
Keluaran
Dalam contoh di atas, kita melihat atribut perintah atau metode yang kita tempatkan di kelas induk sehingga semua subkelas atau kelas anak akan mewarisi properti itu dari kelas induk.
Jika sebuah subclass mencoba mewarisi metode atau data dari subclass lain maka itu akan melalui kesalahan seperti yang kita lihat ketika kelas Dog mencoba memanggil metode swatstring () dari kelas kucing itu, itu melontarkan kesalahan (seperti AttributeError dalam kasus kita).
Polimorfisme ("BANYAK BENTUK")
Polimorfisme adalah fitur penting dari definisi kelas dengan Python yang digunakan ketika Anda memiliki metode yang sering dinamai di seluruh kelas atau subkelas. Ini memungkinkan fungsi untuk menggunakan entitas dari jenis yang berbeda pada waktu yang berbeda. Jadi, ini memberikan fleksibilitas dan kopling longgar sehingga kode dapat diperpanjang dan mudah dipertahankan dari waktu ke waktu.
Hal ini memungkinkan fungsi untuk menggunakan objek dari salah satu kelas polimorfik ini tanpa perlu mengetahui perbedaan di seluruh kelas.
Polimorfisme dapat dilakukan melalui pewarisan, dengan subclass menggunakan metode kelas dasar atau menimpanya.
Mari pahami konsep polimorfisme dengan contoh pewarisan kita sebelumnya dan tambahkan satu metode umum yang disebut show_affection di kedua subclass -
Dari contoh yang bisa kita lihat, ini mengacu pada desain di mana objek dengan tipe yang berbeda dapat diperlakukan dengan cara yang sama atau lebih khusus dua atau lebih kelas dengan metode dengan nama yang sama atau antarmuka umum karena metode yang sama (show_affection dalam contoh di bawah) disebut dengan salah satu jenis objek.
Keluaran
Jadi, semua hewan menunjukkan kasih sayang (show_affection), tetapi mereka melakukannya secara berbeda. Perilaku "show_affection" dengan demikian polimorfik dalam arti bahwa ia bertindak berbeda tergantung pada hewannya. Jadi, konsep “binatang” abstrak sebenarnya tidak “show_affection”, tetapi binatang tertentu (seperti anjing dan kucing) memiliki implementasi konkret dari tindakan “show_affection”.
Python sendiri memiliki kelas yang bersifat polimorfik. Contoh, fungsi len () dapat digunakan dengan banyak objek dan semuanya mengembalikan output yang benar berdasarkan parameter input.
Utama
Di Python, ketika subclass berisi metode yang menggantikan metode superclass, Anda juga bisa memanggil metode superclass dengan memanggil
Super (Subclass, self) .method, bukan self.method.
Contoh
class Thought(object):
def __init__(self):
pass
def message(self):
print("Thought, always come and go")
class Advice(Thought):
def __init__(self):
super(Advice, self).__init__()
def message(self):
print('Warning: Risk is always involved when you are dealing with market!')
Mewarisi Konstruktor
Jika kita melihat dari contoh warisan kita sebelumnya, __init__ terletak di kelas induk di atas karena anjing atau kucing kelas anak tidak memiliki metode __init__ di dalamnya. Python menggunakan pencarian atribut warisan untuk menemukan __init__ di kelas hewan. Ketika kita membuat kelas anak, pertama akan melihat metode __init__ di kelas anjing, kemudian tidak menemukannya kemudian mencari ke kelas induk Animal dan menemukannya di sana dan memanggilnya di sana. Jadi ketika desain kelas kita menjadi kompleks, kita mungkin ingin menginisialisasi sebuah instance terlebih dahulu memprosesnya melalui konstruktor kelas induk dan kemudian melalui konstruktor kelas anak.
Keluaran
Dalam contoh di atas- semua hewan memiliki nama dan semua anjing memiliki ras tertentu. Kami memanggil konstruktor kelas induk dengan super. Jadi anjing memiliki __init__ sendiri tetapi hal pertama yang terjadi adalah kita menyebutnya super. Super adalah fungsi bawaan dan dirancang untuk menghubungkan kelas dengan kelas super atau kelas induknya.
Dalam hal ini kami mengatakan bahwa dapatkan kelas super anjing dan berikan instance anjing ke metode apa pun yang kami katakan di sini konstruktor __init__. Jadi dengan kata lain kita memanggil kelas induk Animal __init__ dengan objek anjing. Anda mungkin bertanya mengapa kami tidak hanya mengatakan Hewan __init__ dengan contoh anjing, kami dapat melakukan ini tetapi jika nama kelas hewan diubah, suatu saat nanti. Bagaimana jika kita ingin menata ulang hierarki kelas, sehingga anjing diwarisi dari kelas lain. Menggunakan super dalam hal ini memungkinkan kita untuk menjaga segala sesuatunya tetap modular dan mudah untuk diubah dan dipelihara.
Jadi dalam contoh ini kami dapat menggabungkan fungsionalitas __init__ umum dengan fungsionalitas yang lebih spesifik. Ini memberi kita kesempatan untuk memisahkan fungsionalitas umum dari fungsionalitas tertentu yang dapat menghilangkan duplikasi kode dan menghubungkan kelas satu sama lain dengan cara yang mencerminkan desain keseluruhan sistem.
Kesimpulan
__init__ seperti metode lainnya; itu bisa diwariskan
Jika sebuah kelas tidak memiliki konstruktor __init__, Python akan memeriksa kelas induknya untuk melihat apakah ia dapat menemukannya.
Begitu menemukannya, Python memanggilnya dan berhenti mencari
Kita bisa menggunakan fungsi super () untuk memanggil metode di kelas induk.
Kita mungkin ingin menginisialisasi di induk serta kelas kita sendiri.
Beberapa Warisan dan Pohon Pencarian
Seperti yang ditunjukkan oleh namanya, multiple inheritance adalah Python ketika kelas mewarisi dari banyak kelas.
Misalnya, seorang anak mewarisi ciri-ciri kepribadian dari kedua orang tuanya (Ibu dan Ayah).
Sintaks Warisan Ganda Python
Untuk membuat kelas mewarisi dari beberapa kelas orang tua, kita menulis nama kelas ini di dalam tanda kurung ke kelas turunan sambil mendefinisikannya. Kami memisahkan nama-nama ini dengan koma.
Di bawah ini adalah contohnya -
>>> class Mother:
pass
>>> class Father:
pass
>>> class Child(Mother, Father):
pass
>>> issubclass(Child, Mother) and issubclass(Child, Father)
True
Warisan berganda mengacu pada kemampuan mewarisi dari dua atau lebih dari dua kelas. Kompleksitas muncul saat anak mewarisi dari orang tua dan orang tua mewarisi dari kelas kakek nenek. Python memanjat pohon yang mewarisi mencari atribut yang diminta untuk dibaca dari suatu objek. Ini akan memeriksa dalam contoh, di dalam kelas kemudian kelas orang tua dan terakhir dari kelas kakek-nenek. Sekarang muncul pertanyaan dalam urutan apa kelas akan dicari - nafas-dulu atau kedalaman-dulu. Secara default, Python menggunakan depth-first.
Itulah sebabnya pada diagram di bawah ini Python mencari metode dothis () terlebih dahulu di kelas A. Jadi urutan resolusi metode pada contoh di bawah ini adalah
Mro- D→B→A→C
Lihatlah diagram beberapa warisan di bawah ini -
Mari kita lihat contoh untuk memahami fitur "mro" dari Python.
Keluaran
Contoh 3
Mari kita ambil contoh lain dari warisan berganda "bentuk berlian".
Diagram di atas akan dianggap ambigu. Dari contoh sebelumnya kita memahami "urutan resolusi metode". Misalnya D → B → A → C → A tetapi tidak. Saat mendapatkan A kedua dari C, Python akan mengabaikan A. sebelumnya sehingga mro dalam hal ini adalah D → B → C → A.
Mari buat contoh berdasarkan diagram di atas -
Keluaran
Aturan sederhana untuk memahami keluaran di atas adalah- jika kelas yang sama muncul dalam urutan resolusi metode, tampilan sebelumnya dari kelas ini akan dihapus dari urutan resolusi metode.
Kesimpulannya -
Setiap kelas dapat mewarisi dari beberapa kelas
Python biasanya menggunakan urutan "kedalaman-pertama" saat mencari kelas yang mewarisi.
Tetapi ketika dua kelas mewarisi dari kelas yang sama, Python menghilangkan kemunculan pertama kelas itu dari mro.
Dekorator, Metode Statis dan Kelas
Fungsi (atau metode) dibuat oleh pernyataan def.
Meskipun metode bekerja dengan cara yang persis sama sebagai fungsi kecuali satu titik di mana argumen pertama metode adalah objek instance.
Kami dapat mengklasifikasikan metode berdasarkan bagaimana mereka berperilaku, seperti
Simple method- didefinisikan di luar kelas. Fungsi ini dapat mengakses atribut kelas dengan memberi makan argumen contoh:
def outside_func(():
Instance method -
def func(self,)
Class method - jika kita perlu menggunakan atribut kelas
@classmethod
def cfunc(cls,)
Static method - tidak memiliki info apa pun tentang kelas
@staticmethod
def sfoo()
Sampai sekarang kita telah melihat metode instance, sekarang saatnya untuk mendapatkan wawasan tentang dua metode lainnya,
Metode Kelas
Dekorator @classmethod, adalah dekorator fungsi bawaan yang meneruskan kelas yang dipanggilnya atau kelas dari instance yang dipanggil sebagai argumen pertama. Hasil evaluasi tersebut membayangi definisi fungsi Anda.
sintaksis
class C(object):
@classmethod
def fun(cls, arg1, arg2, ...):
....
fun: function that needs to be converted into a class method
returns: a class method for function
Mereka memiliki akses ke argumen cls ini, itu tidak dapat mengubah status instance objek. Itu membutuhkan akses ke diri sendiri.
Itu terikat ke kelas dan bukan objek kelas.
Metode kelas masih dapat mengubah status kelas yang berlaku di semua contoh kelas.
Metode Statis
Metode statis tidak mengambil parameter self atau cls (class) tetapi bebas untuk menerima sejumlah parameter lainnya.
syntax
class C(object):
@staticmethod
def fun(arg1, arg2, ...):
...
returns: a static method for function funself.
- Metode statis tidak dapat mengubah status objek maupun status kelas.
- Mereka dibatasi dalam data apa yang dapat mereka akses.
Kapan menggunakan apa
Kami biasanya menggunakan metode kelas untuk membuat metode pabrik. Metode pabrik mengembalikan objek kelas (mirip dengan konstruktor) untuk kasus penggunaan yang berbeda.
Kami biasanya menggunakan metode statis untuk membuat fungsi utilitas.