Apa perbedaan antara up-casting dan down-casting sehubungan dengan variabel kelas

138

Apa perbedaan antara up-casting dan down-casting sehubungan dengan variabel kelas?

Sebagai contoh dalam program berikut, kelas Animal hanya berisi satu metode tetapi kelas Dog berisi dua metode, lalu bagaimana kita melemparkan variabel Dog ke Variabel Hewan.

Jika casting dilakukan maka bagaimana kita dapat memanggil metode Anjing yang lain dengan variabel Animal.

class Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Animal");
    }
}


class Dog extends Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Dog");
    }

    public void callme2()
    {
        System.out.println("In callme2 of Dog");
    }
}

public class UseAnimlas 
{
    public static void main (String [] args) 
    {
        Dog d = new Dog();      
        Animal a = (Animal)d;
        d.callme();
        a.callme();
        ((Dog) a).callme2();
    }
}
Dhivakar
sumber
A Dogadalah sebuah Animal. Sebagian besar waktu siaran tidak perlu kecuali jika Anda ingin menggunakan metode kelebihan beban tertentu. callmeada di keduanya Animaldan Dog. callme2hanya ada di Dog, yang Anda melemparkan auntuk Doguntuk membuatnya bekerja.
Brian
Apa output dari kode Anda?
Malwinder Singh
Yang menarik adalah, bahwa d.callme mengembalikan 'In callme of Dog' meskipun d dilemparkan ke binatang !!
Chris311
4
@ Chris311 baik 'd' dan 'a' menunjuk ke objek yang sama ... yang merupakan Dog, tetapi 'a' memiliki akses ke metode khusus Dog saja ketika sedang downcast saat runtime. Infact: Animal a = (Animal) d; tidak perlu, Anda hanya perlu Animal a = d; saat Anda sedang upcasting.
Mark Keen

Jawaban:

223

Upcasting adalah casting ke supertype, sedangkan downcasting casting ke subtipe. Upcasting selalu diizinkan, tetapi downcasting melibatkan pemeriksaan jenis dan dapat membuang a ClassCastException.

Dalam kasus Anda, para pemeran dari a Dogke a Animaladalah orang yang dibuang, karena a Dog-a Animal. Secara umum, Anda dapat menghapus setiap kali ada hubungan antara dua kelas.

Downcasting akan menjadi seperti ini:

Animal animal = new Dog();
Dog castedDog = (Dog) animal;

Pada dasarnya apa yang Anda lakukan adalah memberi tahu kompiler bahwa Anda tahu apa jenis objek runtime sebenarnya . Kompiler akan mengizinkan konversi, tetapi masih akan memasukkan pemeriksaan kewarasan runtime untuk memastikan bahwa konversi masuk akal. Dalam hal ini, para pemain ini dimungkinkan karena pada saat runtime animalsebenarnya Dogmeskipun jenis statis animaladalah Animal.

Namun, jika Anda melakukan ini:

Animal animal = new Animal();
Dog notADog = (Dog) animal;

Anda akan mendapat ClassCastException. Alasan mengapa karena animaljenis runtime adalah Animal, dan ketika Anda memberitahu runtime untuk melakukan pemeran itu melihat itu animaltidak benar-benar Dogdan melemparkan ClassCastException.

Untuk memanggil metode superclass, Anda dapat melakukan super.method()atau dengan melakukan upcast.

Untuk memanggil metode subclass, Anda harus melakukan downcast. Seperti yang ditunjukkan di atas, Anda biasanya mengambil risiko ClassCastExceptiondengan melakukan ini; Namun, Anda dapat menggunakan instanceofoperator untuk memeriksa jenis runtime objek sebelum melakukan gips, yang memungkinkan Anda untuk mencegah ClassCastExceptions:

Animal animal = getAnimal(); // Maybe a Dog? Maybe a Cat? Maybe an Animal?
if (animal instanceof Dog) {
    // Guaranteed to succeed, barring classloader shenanigans
    Dog castedDog = (Dog) animal;
}
awksp
sumber
Apakah downcasting yang tepat memastikan tidak ClassCastExceptionatau tidak? Seperti dalam kasus pertama?
Malwinder Singh
@ MS Apa yang Anda maksud dengan "pantas"?
awksp
2
@awksp Ini adalah jawaban yang sangat bagus dan jelas. Cukup banyak meringkas semua yang perlu saya ketahui tentang Casting.
Gautham Honnavara
tentunya Anda belum membuat kelas di mana hewan adalah contoh anjing, bukan? jadi mengapa Anda bahkan memeriksanya?
barlop
62

Down-casting dan up-casting adalah sebagai berikut:
masukkan deskripsi gambar di sini

Upcasting : Ketika kami ingin memberikan Sub class ke Super class, kami menggunakan Upcasting (atau pelebaran). Itu terjadi secara otomatis, tidak perlu melakukan apa pun secara eksplisit.

Downcasting : Ketika kita ingin melemparkan kelas Super ke kelas Sub, kita menggunakan Downcasting (atau penyempitan), dan Downcasting tidak secara langsung mungkin di Jawa, secara eksplisit harus kita lakukan.

Dog d = new Dog();
Animal a = (Animal) d; //Explicitly you have done upcasting. Actually no need, we can directly type cast like Animal a = d; compiler now treat Dog as Animal but still it is Dog even after upcasting
d.callme();
a.callme(); // It calls Dog's method even though we use Animal reference.
((Dog) a).callme2(); // Downcasting: Compiler does know Animal it is, In order to use Dog methods, we have to do typecast explicitly.
// Internally if it is not a Dog object it throws ClassCastException
Premraj
sumber
Jadi, tidak ada cara seperti melakukan upcasting untuk memanggil orang tua metode ini?
karlihnos
32

Upcasting dan downcasting adalah bagian penting dari Java, yang memungkinkan kita untuk membangun program rumit menggunakan sintaksis sederhana, dan memberi kita keuntungan besar, seperti Polimorfisme atau pengelompokan objek yang berbeda. Java memungkinkan objek tipe subclass untuk diperlakukan sebagai objek dari tipe superclass apa pun. Ini disebut upcasting. Upcasting dilakukan secara otomatis, sementara downcasting harus dilakukan secara manual oleh programmer , dan saya akan memberikan yang terbaik untuk menjelaskan mengapa demikian.

Upcasting dan downcasting TIDAK seperti casting primitif dari satu ke yang lain, dan saya percaya itulah yang menyebabkan banyak kebingungan, ketika programmer mulai belajar benda casting.

Polimorfisme: Semua metode di java adalah virtual secara default. Itu berarti bahwa metode apa pun dapat diganti ketika digunakan dalam warisan, kecuali metode itu dinyatakan final atau statis .

Anda dapat melihat contoh di bawah ini cara getType();kerjanya sesuai dengan jenis objek (Anjing, Hewan Peliharaan, Anjing Polisi).

Anggaplah Anda memiliki tiga anjing

  1. Anjing - Ini adalah Kelas super.

  2. Pet Dog - Pet Dog memanjang Anjing.

  3. Polisi Anjing - Anjing Polisi memperpanjang Anjing Peliharaan.

    public class Dog{ 
       public String getType () {
          System.out.println("NormalDog");
          return "NormalDog";
       }
     }
    
    /**
     * Pet Dog has an extra method dogName()
     */   
    public class PetDog extends Dog{ 
       public String getType () {
          System.out.println("PetDog");
          return "PetDog";
       }
       public String dogName () {
          System.out.println("I don't have Name !!");
          return "NO Name";
       }
     }
    
    /**
     * Police Dog has an extra method secretId()
     */
    public class PoliceDog extends PetDog{
    
     public String secretId() {
        System.out.println("ID");
        return "ID";
     }
    
     public String getType () {
         System.out.println("I am a Police Dog");
         return "Police Dog";
     }
    }

Polimorfisme: Semua metode di java adalah virtual secara default. Itu berarti bahwa metode apa pun dapat diganti ketika digunakan dalam warisan, kecuali metode itu dinyatakan final atau statis. (Penjelasan Milik Konsep Tabel Virtual)

Tabel Virtual / Tabel Pengiriman: Tabel pengiriman objek akan berisi alamat metode yang terikat secara dinamis pada objek. Metode panggilan dilakukan dengan mengambil alamat metode dari tabel pengiriman objek. Tabel pengiriman adalah sama untuk semua objek milik kelas yang sama, dan karena itu biasanya dibagi di antara mereka.

public static void main (String[] args) {
      /**
       * Creating the different objects with super class Reference
       */
     Dog obj1 = new Dog();
`         /**
           *  Object of Pet Dog is created with Dog Reference since                
           *  Upcasting is done automatically for us we don't have to worry about it 
           *  
           */
     Dog obj2 = new PetDog();
`         /**
           *  Object of Police Dog is created with Dog Reference since                
           *  Upcasting is done automatically for us we don't have to worry       
           *  about it here even though we are extending PoliceDog with PetDog 
           *  since PetDog is extending Dog Java automatically upcast for us 
           */
      Dog obj3 = new PoliceDog();
}



 obj1.getType();

Cetakan Normal Dog

  obj2.getType();

Cetakan Pet Dog

 obj3.getType();

Cetakan Police Dog

Downcasting perlu dilakukan oleh programmer secara manual

Ketika Anda mencoba untuk memanggil secretID();metode obj3yang PoliceDog objecttetapi direferensikan Dogyang merupakan kelas super dalam hierarki itu melempar kesalahan karena obj3tidak memiliki akses ke secretId()metode. Untuk memanggil metode itu, Anda perlu Downcast bahwa obj3 secara manual PoliceDog

  ( (PoliceDog)obj3).secretID();

yang mencetak ID

Dalam cara yang sama untuk memohon dogName();metode dalam PetDogkelas Anda perlu tertunduk obj2untuk PetDogsejak obj2 dirujuk ke Dogdan tidak memiliki akses ke dogName();metode

  ( (PetDog)obj2).dogName();

Mengapa demikian, bahwa upcasting bersifat otomatis, tetapi downcasting harus manual? Anda tahu, upcasting tidak pernah gagal. Tapi jika Anda memiliki sekelompok berbeda Anjing dan ingin tertunduk mereka semua untuk jenis mereka, maka ada kesempatan, bahwa beberapa Anjing ini sebenarnya dari jenis yang berbeda yaitu, PetDog, PoliceDog, dan proses gagal, dengan melempar ClassCastException.

Ini adalah alasan Anda perlu menurunkan objek Anda secara manual jika Anda telah mereferensikan objek Anda ke tipe kelas super.

Catatan: Di sini dengan merujuk berarti Anda tidak mengubah alamat memori dari oject Anda ketika Anda menurunkannya masih tetap sama, Anda hanya mengelompokkannya ke jenis tertentu dalam kasus ini. Dog

Nagarjuna Yelisetty
sumber
'Polimorfisme menggunakan downcast otomatis selama panggilan metode.' Tidak, tidak. Mekanisme yang digunakan tidak ditentukan, tetapi mekanisme yang paling umum - vtable - tidak melakukan hal seperti itu. Lihat di kode objek. Tidak ada downcast.
Marquis of Lorne
Kenapa tidak? Inilah yang terjadi, dapatkah Anda memberi contoh di mana itu tidak akan berhasil?
Nagarjuna Yelisetty
1
Kenapa tidak? Inilah yang terjadi dengan benar .. dapatkah Anda memberikan contoh di mana pernyataan 'Polimorfisme menggunakan downcast otomatis selama pemanggilan metode'. akan gagal atau tidak akan berlaku?
Nagarjuna Yelisetty
Ini pendapat Anda. Terserah Anda untuk membuktikannya. Tunjukkan di mana dalam kode objek downcast terjadi. Jawaban untuk pertanyaan 'mengapa tidak' adalah 'karena itu tidak perlu'. Vtable menangani pengiriman metode, dan variabel sudah menunjuk ke seluruh objek.
Marquis of Lorne
1
'Sesuai pengetahuan saya, pernyataan saya benar dan itu berlaku dalam setiap kasus' bukan bukti. Itu hanya pernyataan. Saya meminta Anda untuk membuktikan pernyataan Anda . Anda tidak melakukannya. Akibatnya Anda hanya mengulangi diri Anda sendiri. Dan saya sudah memberikan beberapa sanggahan. Saya juga sudah menyediakan prosedur keputusan. Jika Anda dapat menemukan downcast dalam kode objek untuk pemanggilan metode, Anda benar dan saya salah. Beginilah cara sains dilakukan. Lakukan. Dan mengklaim bahwa saya 'berani bergantung pada dokumentasi' adalah pernyataan keliru yang terang-terangan. Jangan lakukan itu.
Marquis of Lorne
12

Saya tahu pertanyaan ini sudah lama ditanyakan tetapi untuk pengguna baru pertanyaan ini. Silakan baca artikel ini di mana berisi deskripsi lengkap tentang upcasting, downcasting, dan penggunaan instanceof operator

  • Tidak perlu untuk dihapus secara manual, itu terjadi sendiri:

    Mammal m = (Mammal)new Cat(); sama dengan Mammal m = new Cat();

  • Tetapi downcasting harus selalu dilakukan secara manual:

    Cat c1 = new Cat();      
    Animal a = c1;      //automatic upcasting to Animal
    Cat c2 = (Cat) a;    //manual downcasting back to a Cat

Mengapa demikian, bahwa upcasting bersifat otomatis, tetapi downcasting harus manual? Anda tahu, upcasting tidak pernah gagal. Tetapi jika Anda memiliki sekelompok Hewan yang berbeda dan ingin menurunkan mereka semua ke Kucing, maka ada kemungkinan, bahwa beberapa Hewan ini sebenarnya adalah Anjing, dan prosesnya gagal, dengan melempar ClassCastException. Di sinilah harus memperkenalkan fitur berguna yang disebut "instanceof" , yang menguji apakah suatu objek adalah instance dari beberapa Kelas.

 Cat c1 = new Cat();         
    Animal a = c1;       //upcasting to Animal
    if(a instanceof Cat){ // testing if the Animal is a Cat
        System.out.println("It's a Cat! Now i can safely downcast it to a Cat, without a fear of failure.");        
        Cat c2 = (Cat)a;
    }

Untuk informasi lebih lanjut silakan baca artikel ini

Nadeesha Thilakarathne
sumber
poin bagus: Mamalia m = (Mamalia) Kucing baru (); sama dengan Mamalia m = Kucing baru ();
Catbuilts
6

Lebih baik coba metode ini untuk upcasting, mudah dimengerti:

/* upcasting problem */
class Animal
{ 
    public void callme()
    {
        System.out.println("In callme of Animal");
    }
}

class Dog extends Animal 
{ 
    public void callme()
    {
        System.out.println("In callme of Dog");
    }

    public void callme2()
    {
        System.out.println("In callme2 of Dog");
    }
}

public class Useanimlas 
{
    public static void main (String [] args) 
    {
        Animal animal = new Animal ();
        Dog dog = new Dog();
        Animal ref;
        ref = animal;
        ref.callme();
        ref = dog;
        ref.callme();
    }
}
UWAIS
sumber
dan di baris terakhir bisa jadi: ((Dog) ref) .callme2 (); // untuk akses metode downcasting / narrowing dan callme2 () dari kelas Dog.
udarH3
6

Mungkin tabel ini membantu. Memanggil callme()metode kelas Parentatau kelas Child. Sebagai prinsip:

UPCASTING -> Menyembunyikan

MUNDUR -> Mengungkap

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

Alexis
sumber
4

1.- Siaran.

Melakukan upcasting, Anda menetapkan tag dari beberapa jenis, yang menunjuk ke objek subtipe (Jenis dan subtipe dapat disebut kelas dan subkelas, jika Anda merasa lebih nyaman ...).

Animal animalCat = new Cat();

Apa artinya bahwa tag tersebut, animalCat, akan memiliki fungsionalitas (metode) dari tipe Hewan saja, karena kami telah mendeklarasikannya sebagai tipe Hewan, bukan sebagai tipe Kucing.

Kami diizinkan untuk melakukannya dengan cara "alami / implisit / otomatis", pada waktu kompilasi atau pada saat run-time, terutama karena Cat mewarisi beberapa fungsinya dari Animal; misalnya, pindah (). (Setidaknya, kucing adalah binatang, bukan?)

2.- Downcasting.

Tapi, apa yang akan terjadi jika kita perlu mendapatkan fungsionalitas Cat, dari tag Animal type kita ?.

Karena kami telah membuat tag animalCat yang menunjuk ke objek Cat, kami membutuhkan cara untuk memanggil metode objek Cat, dari tag animalCat kami dengan cara yang cukup cerdas.

Prosedur semacam itu adalah apa yang kita sebut Downcasting, dan kita dapat melakukannya hanya pada saat run-time.

Waktu untuk beberapa kode:

public class Animal {
    public String move() {
        return "Going to somewhere";
    }
}

public class Cat extends Animal{
    public String makeNoise() {
        return "Meow!";
    }   
}

public class Test {

    public static void main(String[] args) {
        
    //1.- Upcasting 
    //  __Type_____tag________object
        Animal animalCat = new Cat();
    //Some animal movement
        System.out.println(animalCat.move());
        //prints "Going to somewhere"
        
    //2.- Downcasting   
    //Now you wanna make some Animal noise.
        //First of all: type Animal hasn't any makeNoise() functionality.
        //But Cat can do it!. I wanna be an Animal Cat now!!
        
        //___________________Downcast__tag_____ Cat's method
        String animalNoise = ( (Cat) animalCat ).makeNoise();
        
        System.out.println(animalNoise);
        //Prints "Meow!", as cats usually done.
        
    //3.- An Animal may be a Cat, but a Dog or a Rhinoceros too.
        //All of them have their own noises and own functionalities.
        //Uncomment below and read the error in the console:
        
    //  __Type_____tag________object
        //Cat catAnimal = new Animal();
        
    }

}
Lemmy_Caution
sumber
2

Induk: Mobil
Anak: Figo
Mobil c1 = Figo baru ();

=====
Upcasting: -
Metode: Objek c1 akan merujuk ke Metode Kelas (Figo - Metode harus diganti) karena kelas "Figo" ditentukan dengan "baru".
Variabel Instance: Objek c1 akan merujuk ke variabel instan dari Kelas Deklarasi ("Mobil").

Ketika kelas Deklarasi adalah orang tua dan objek dibuat dari anak, maka casting implisit terjadi yaitu "Upcasting".

======
Downcasting: -
Figo f1 = (Figo) c1; //
Metode: Objek f1 akan merujuk ke Metode Kelas (figo) sebagai objek awal c1 dibuat dengan kelas "Figo". tetapi setelah pengecoran selesai, metode yang hanya ada di kelas "Figo" juga dapat dirujuk oleh variabel f1.
Variabel Instance: Objek f1 tidak akan merujuk ke variabel instan dari kelas Deklarasi objek c1 (kelas deklarasi untuk c1 adalah CAR) tetapi dengan down casting akan merujuk ke variabel instance dari kelas Figo.

======
Gunakan: Ketika Objek adalah dari Kelas Anak dan kelas deklarasi adalah Orang Tua dan kelas Anak ingin mengakses variabel Instance dari kelas itu sendiri dan bukan dari kelas induk maka dapat dilakukan dengan "Downcasting".

amit shah
sumber
1

upcasting berarti casting objek ke supertype, sedangkan downcasting berarti casting ke subtype.

Di java, upcasting tidak perlu karena dilakukan secara otomatis. Dan biasanya disebut casting implisit. Anda dapat menentukannya untuk menjelaskan kepada orang lain.

Demikian tulisan

Animal a = (Animal)d;

atau

Animal a = d;

mengarah ke titik yang sama persis dan dalam kedua kasus akan dieksekusi callme()dari Dog.

Downcasting sebaliknya diperlukan karena Anda didefinisikan asebagai objek Animal. Saat ini Anda tahu itu adalah Dog, tetapi java tidak memiliki jaminan itu. Sebenarnya saat runtime bisa berbeda dan java akan melempar ClassCastException, apakah itu akan terjadi. Tentu saja bukan itu contoh contoh Anda sendiri. Jika Anda tidak akan dilemparkan ake Animaljava, bahkan tidak bisa mengkompilasi aplikasi karena Animaltidak memiliki metode callme2().

Dalam contoh Anda tidak dapat mencapai kode callme()dari Animaldari UseAnimlas(karena Dogmenimpa itu) kecuali metode akan sebagai berikut:

class Dog extends Animal 
{ 
    public void callme()
    {
        super.callme();
        System.out.println("In callme of Dog");
    }
    ... 
} 
David
sumber
0

Kita dapat membuat objek ke Downcasting. Dalam tipe ini juga. : memanggil metode kelas dasar

Animal a=new Dog();
a.callme();
((Dog)a).callme2();
Rakesh
sumber