"Amigo, apakah kamu suka ikan paus?"

"Paus? Tidak, tidak pernah mendengar tentang mereka."

"Ini seperti sapi, hanya lebih besar dan berenang. Kebetulan, paus berasal dari sapi. Uh, atau setidaknya mereka memiliki nenek moyang yang sama. Tidak masalah."

Polimorfisme dan overriding - 1

"Dengar. Saya ingin memberi tahu Anda tentang alat OOP lain yang sangat ampuh: polimorfisme . Ini memiliki empat fitur."

1) Metode menimpa.

Bayangkan Anda telah menulis kelas "Sapi" untuk sebuah game. Ini memiliki banyak variabel dan metode anggota. Objek kelas ini dapat melakukan berbagai hal: berjalan, makan, tidur. Sapi juga membunyikan lonceng saat mereka berjalan. Katakanlah Anda telah mengimplementasikan semua yang ada di kelas hingga ke detail terkecil.

Polimorfisme dan overriding - 2

Lalu tiba-tiba pelanggan mengatakan ingin merilis level baru dari game tersebut, di mana semua aksi terjadi di laut, dan karakter utamanya adalah ikan paus.

Anda mulai mendesain kelas Paus dan menyadari bahwa itu hanya sedikit berbeda dari kelas Sapi. Kedua kelas menggunakan logika yang sangat mirip, dan Anda memutuskan untuk menggunakan pewarisan.

Kelas Cow cocok untuk menjadi kelas induk: ia sudah memiliki semua variabel dan metode yang diperlukan. Yang perlu Anda lakukan hanyalah menambah kemampuan paus untuk berenang. Tapi ada masalah: paus Anda memiliki kaki, tanduk, dan lonceng. Lagi pula, kelas Sapi mengimplementasikan fungsi ini. Apa yang bisa kau lakukan?

Polimorfisme dan overriding - 3

Metode overriding datang untuk menyelamatkan. Jika kita mewarisi metode yang tidak melakukan apa yang kita butuhkan di kelas baru kita, kita dapat mengganti metode tersebut dengan yang lain.

Polimorfisme dan overriding - 4

Bagaimana ini dilakukan? Di kelas turunan, kami mendeklarasikan metode yang ingin kami ubah (dengan tanda tangan metode yang sama seperti di kelas induk) . Kemudian kami menulis kode baru untuk metode tersebut. Itu dia. Seolah-olah metode lama kelas induk tidak ada.

Begini cara kerjanya:

Kode Keterangan
class Cow
{
public void printColor()
{
System.out.println("I'm white");
}
public void printName()
{
System.out.println("I'm a cow");
}
}class Whale extends Cow
{
public void printName()
{
System.out.println("I'm a whale");
}
}
Di sini kita mendefinisikan dua kelas:  Cow dan  WhaleWhalemewarisi  Cow.

Kelas  Whale menimpa  printName();metode.

public static void main(String[] args)
{
Cow cow = new Cow();
cow.printName();
}
Kode ini menampilkan « Saya seekor sapi » di layar.
public static void main(String[] args)
{
Whale whale = new Whale();
whale.printName();
}
Kode ini menampilkan « Saya seekor paus » di layar

Setelah mewarisi Cowdan menimpa printName, Whalekelas sebenarnya memiliki data dan metode berikut:

Kode Keterangan
class Whale
{
public void printColor()
{
System.out.println("I'm white");
}
public void printName()
{
System.out.println("I'm a whale");
}
}
Kami tidak tahu apa-apa tentang metode lama apa pun.

"Jujur, itu yang kuharapkan."

2) Tapi itu belum semuanya.

"Misalkan  Cow kelas memiliki  printAll, metode yang memanggil dua metode lainnya. Maka kodenya akan bekerja seperti ini:"

Layar akan menampilkan:
Saya putih
Saya seekor ikan paus

Kode Keterangan
class Cow
{
public void printAll()
{
printColor();
printName();
}
public void printColor()
{
System.out.println("I'm white");
}
public void printName()
{
System.out.println("I'm a cow");
}
}

class Whale extends Cow
{
public void printName()
{
System.out.println("I'm a whale");
}
}
public static void main(String[] args)
{
Whale whale = new Whale();
whale.printAll();
}
Layar akan menampilkan:
Saya putih
Saya seekor ikan paus

Perhatikan bahwa ketika metode printAll () kelas Cow dipanggil pada objek Whale, metode printName() Whale akan digunakan, bukan Cow.

Yang penting bukanlah kelas tempat metode ditulis, melainkan tipe (kelas) objek tempat metode dipanggil.

"Jadi begitu."

"Anda hanya dapat mewarisi dan mengganti metode non-statis. Metode statis tidak diwariskan dan karena itu tidak dapat diganti."

Inilah tampilan kelas Whale setelah kita menerapkan pewarisan dan mengganti metode:

Kode Keterangan
class Whale
{
public void printAll()
{
printColor();
printName();
}
public void printColor()
{
System.out.println("I'm white");
}
public void printName()
{
System.out.println("I'm a whale");
}
}
Inilah tampilan kelas Whale setelah kita menerapkan pewarisan dan mengganti metode. Kami tidak tahu apa-apa tentang printNamemetode lama apa pun.

3) Ketik pengecoran.

Inilah poin yang lebih menarik. Karena sebuah kelas mewarisi semua metode dan data dari kelas induknya, sebuah objek dari kelas ini dapat direferensikan oleh variabel dari kelas induk (dan induk dari induk, dll., hingga kelas Object). Pertimbangkan contoh ini:

Kode Keterangan
public static void main(String[] args)
{
Whale whale = new Whale();
whale.printColor();
}
Layar akan menunjukkan:
Saya putih.
public static void main(String[] args)
{
Cow cow = new Whale();
cow.printColor();
}
Layar akan menunjukkan:
Saya putih.
public static void main(String[] args)
{
Object o = new Whale();
System.out.println(o.toString());
}
Layar akan menampilkan:
Whale@da435a.
Metode toString() diwariskan dari kelas Object.

"Bagus. Tapi kenapa kamu membutuhkan ini?"

"Ini fitur yang berharga. Anda akan mengerti nanti bahwa ini sangat, sangat berharga."

4) Pengikatan terlambat (pengiriman dinamis).

Berikut tampilannya:

Kode Keterangan
public static void main(String[] args)
{
Whale whale = new Whale();
whale.printName();
}
Layar akan menampilkan:
Saya seekor paus.
public static void main(String[] args)
{
Cow cow = new Whale();
cow.printName();
}
Layar akan menampilkan:
Saya seekor paus.

Perhatikan bahwa bukan tipe variabel yang menentukan metode printName spesifik mana yang kita panggil (kelas Cow atau Whale), melainkan tipe objek yang direferensikan oleh variabel.

Variabel Cow menyimpan referensi ke objek Whale , dan metode printName yang didefinisikan dalam kelas Whale akan dipanggil.

"Yah, mereka tidak menambahkan itu demi kejelasan."

"Ya, tidak terlalu jelas. Ingat aturan penting ini:"

Himpunan metode yang dapat Anda panggil pada variabel ditentukan oleh tipe variabel. Tetapi metode/implementasi spesifik mana yang dipanggil ditentukan oleh jenis/kelas objek yang direferensikan oleh variabel.

"Saya akan mencoba."

"Kamu akan mengalami ini terus-menerus, jadi kamu akan segera memahaminya dan tidak pernah lupa."

5) Ketik pengecoran.

Casting bekerja secara berbeda untuk tipe referensi, yaitu kelas, daripada tipe primitif. Namun, konversi pelebaran dan penyempitan juga berlaku untuk jenis referensi. Pertimbangkan contoh ini:

Konversi pelebaran Keterangan
Cow cow = new Whale();

Konversi pelebaran klasik. Sekarang Anda hanya bisa memanggil metode yang didefinisikan dalam kelas Cow pada objek Whale.

Kompiler akan mengizinkan Anda menggunakan variabel cow hanya untuk memanggil metode yang ditentukan oleh tipe Cow.

Mempersempit konversi Keterangan
Cow cow = new Whale();
if (cow instanceof Whale)
{
Whale whale = (Whale) cow;
}
Konversi penyempitan klasik dengan pemeriksaan tipe. Variabel cow bertipe Cow menyimpan referensi ke objek Whale.
Kami memeriksa apakah ini masalahnya , dan kemudian melakukan konversi jenis (pelebaran). Ini juga disebut pengecoran tipe .
Cow cow = new Cow();
Whale whale = (Whale) cow; //exception
Anda juga dapat melakukan konversi penyempitan tipe referensi tanpa memeriksa tipe objek.
Dalam hal ini, jika variabel cow menunjuk pada sesuatu selain objek Whale, pengecualian (InvalidClassCastException) akan dilontarkan.

6) Dan sekarang untuk sesuatu yang enak. Memanggil metode asli.

Terkadang saat mengganti metode yang diwariskan, Anda tidak ingin menggantinya sepenuhnya. Terkadang Anda hanya ingin menambahkan sedikit saja.

Dalam hal ini, Anda benar-benar ingin kode metode baru memanggil metode yang sama, tetapi pada kelas dasar. Dan Java mari kita lakukan ini. Begini caranya:  super.method().

Berikut beberapa contohnya:

Kode Keterangan
class Cow
{
public void printAll()
{
printColor();
printName();
}
public void printColor()
{
System.out.println("I'm white");
}
public void printName()
{
System.out.println("I'm a cow");
}
}

class Whale extends Cow
{
public void printName()
{
System.out.print("This is false: ");
super.printName();

System.out.println("I'm a whale");
}
}
public static void main(String[] args)
{
Whale whale = new Whale();
whale.printAll();
}
Layar akan menampilkan:
Saya putih
Ini salah: Saya sapi,
saya paus

"Hmm. Yah, itu pelajaran. Telinga robotku hampir meleleh."

"Ya, ini bukan hal yang sederhana. Ini adalah beberapa materi yang paling sulit yang akan Anda temui. Profesor berjanji untuk memberikan tautan ke materi dari penulis lain, sehingga jika Anda masih tidak memahami sesuatu, Anda dapat mengisinya. celah."