"Hai, Amigo! Topik pelajaran hari ini adalah konversi tipe pelebaran dan penyempitan. Anda sudah lama belajar tentang pelebaran dan penyempitan tipe primitif. Di Level 10. Hari ini kita akan berbicara tentang cara kerjanya untuk tipe referensi, yaitu contoh kelas."

Faktanya, semuanya cukup sederhana. Bayangkan rantai pewarisan kelas: kelas, induknya, induk dari induk, dll., hingga kembali ke kelas Object. Karena sebuah kelas berisi semua metode anggota dari kelas yang diwarisinya , turunan dari kelas tersebut dapat disimpan dalam variabel yang bertipe salah satu induknya.

Berikut contohnya:

Kode Keterangan
class Animal
{
public void doAnimalActions();
}class Cat extends Animal
{
public void doCatActions();
}class Tiger extends Cat
{
public void doTigerActions();
}
Di sini kita memiliki tiga deklarasi kelas: Animal, Cat, dan Tiger. Kucing mewarisi Hewan. Dan Tiger mewarisi Cat.
public static void main(String[] args)
{
Tiger tiger = new Tiger();
Cat cat = new Tiger();
Animal animal = new Tiger();
Object obj = new Tiger();
}
Objek Tiger selalu dapat ditugaskan ke variabel yang tipenya adalah salah satu leluhurnya. Untuk class Tiger, ini adalah Cat, Animal, dan Object.

Sekarang mari kita lihat perluasan dan penyempitan konversi.

Jika operasi penugasan menyebabkan kita naik rantai pewarisan (menuju kelas Object), maka kita berurusan dengan konversi pelebaran (juga dikenal sebagai upcasting). Jika kita bergerak ke bawah rantai menuju tipe objek, maka itu adalah konversi penyempitan (juga dikenal sebagai downcasting).

Menaikkan rantai pewarisan disebut pelebaran, karena mengarah ke tipe yang lebih umum. Namun, dengan melakukan itu kita kehilangan kemampuan untuk memanggil metode yang ditambahkan ke kelas melalui pewarisan.

Kode Keterangan
public static void main(String[] args)
{
Object obj = new Tiger();
Animal animal = (Animal) obj;
Cat cat = (Cat) obj;
Tiger tiger = (Tiger) animal;
Tiger tiger2 = (Tiger) cat;
}
Saat mempersempit jenis, Anda perlu menggunakan operator konversi jenis, yaitu kami melakukan konversi eksplisit.

Hal ini menyebabkan mesin Java memeriksa apakah objek tersebut benar-benar mewarisi tipe yang ingin kita ubah.

Inovasi kecil ini menghasilkan pengurangan berlipat ganda dalam jumlah kesalahan pengecoran tipe, dan secara signifikan meningkatkan stabilitas program Java.

Kode Keterangan
public static void main(String[] args)
{
Object obj = new Tiger();
if (obj instanceof Cat)
{
Cat cat = (Cat) obj;
cat.doCatActions();
}}
Lebih baik lagi, gunakan  instanceof check
public static void main(String[] args)
{
Animal animal = new Tiger();
doAllAction(animal);

Animal animal2 = new Cat();
doAllAction(animal2);

Animal animal3 = new Animal();
doAllAction(animal3);
}

public static void doAllAction(Animal animal)
{
if (animal instanceof Tiger)
{
Tiger tiger = (Tiger) animal;
tiger.doTigerActions();
}

if (animal instanceof Cat)
{
Cat cat = (Cat) animal;
cat.doCatActions();
}

animal.doAnimalActions();
}
Dan inilah alasannya. Lihatlah contoh di sebelah kiri.

Kami (kode kami) tidak selalu tahu jenis objek apa yang sedang kami kerjakan. Itu bisa berupa objek dengan tipe yang sama dengan variabel (Hewan), atau tipe keturunan apa pun (Kucing, Harimau).

Pertimbangkan metode doAllAction. Ini berfungsi dengan benar, terlepas dari jenis objek yang diteruskan.

Dengan kata lain, ini berfungsi dengan baik untuk ketiga jenis: Hewan, Kucing, dan Harimau.

public static void main(String[] args)
{
Cat cat = new Tiger();
Animal animal = cat;
Object obj = cat;
}
Di sini kita memiliki tiga operasi penugasan. Semuanya adalah contoh pelebaran konversi.

Operator pemeran tipe tidak diperlukan di sini, karena tidak diperlukan pemeriksaan. Referensi objek selalu dapat disimpan dalam variabel yang tipenya adalah salah satu leluhurnya.

"Oh, contoh kedua hingga terakhir membuat semuanya jelas: mengapa pemeriksaan diperlukan, dan mengapa pengecoran tipe diperlukan."

"Saya harap begitu. Saya ingin menarik perhatian Anda pada fakta ini:"

Semua ini tidak menyebabkan objek berubah dengan cara apa pun! Satu-satunya hal yang berubah adalah jumlah metode yang tersedia untuk dipanggil pada variabel referensi tertentu.

Misalnya, variabel Cat memungkinkan Anda memanggil metode doAnimalActions dan doCatActions. Itu tidak tahu apa-apa tentang metode doTigerActions, bahkan jika itu menunjuk ke objek Tiger.

"Ya, saya mengerti. Itu lebih mudah dari yang saya kira."