tertunduk dan tertekan

88

Saya baru mengenal C # (dan OOP ). Ketika saya memiliki beberapa kode seperti berikut:

class Employee
{
    // some code
}


class Manager : Employee
{
    //some code
}

Pertanyaan 1 : Jika saya memiliki kode lain yang melakukan ini:

   Manager mgr = new Manager();
   Employee emp = (Employee)mgr;

Ini Employeea Manager, tetapi ketika saya melemparkannya seperti itu ke sebuah Employeeartinya saya sedang meningkatkannya?

Pertanyaan 2 :

Ketika saya memiliki beberapa Employeeobjek kelas dan beberapa tetapi tidak semuanya adalah Manager, bagaimana saya bisa menurunkannya jika memungkinkan?

pengguna184805
sumber
6
Upcasting bisa dilakukan tanpa cast eksplisit. Jadi Employee emp= mgr;seharusnya sudah cukup.
cium ketiak saya

Jawaban:

95
  1. Itu betul. Ketika Anda melakukannya, Anda akan mentransmisikannya ke dalam sebuah employeeobjek, jadi itu berarti Anda tidak dapat mengakses apa pun yang spesifik untuk pengelola.

  2. Downcasting adalah saat Anda mengambil kelas dasar dan kemudian mencoba mengubahnya menjadi kelas yang lebih spesifik. Ini dapat dilakukan dengan menggunakan is dan cast eksplisit seperti ini:

    if (employee is Manager)
    {
        Manager m = (Manager)employee;
        //do something with it
    }
    

atau dengan asoperator seperti ini:

Manager m = (employee as Manager);
if (m != null)
{
    //do something with it
}

Jika ada yang tidak jelas, saya akan dengan senang hati memperbaikinya!

RCIX
sumber
Saya perlu contoh untuk mengetahui apa itu Downcasting?
pengguna184805
4
Hindari mendefinisikan ulang istilah yang sudah mapan: "tinju", dalam konteks OOP dan C #, berarti sesuatu yang agak berbeda (= membungkus objek tipe nilai menjadi referensi). Juga, contoh Anda bisa (dan seharusnya) menggunakan asoperator, bukan is, diikuti oleh cast.
Konrad Rudolph
2
Saya berdiri dikoreksi pada poin pertama, dan saya mengubah paruh kedua jawaban saya untuk menunjukkan kedua cara melakukannya.
RCIX
3
Pernyataan pertama Anda ("... mentransmisikan [turunan kelas Manajer] ke dalam objek" karyawan "[..] berarti Anda tidak dapat mengakses apa pun yang spesifik untuk manajer") tidak sepenuhnya akurat. Dalam contoh OP, jika Karyawan memiliki anggota virtual yang diganti di Manajer, CLR akan memanggil implementasi Manajer, terlepas dari adanya cast. Dari artikel MSDN tentang polimorfisme di C #: "Ketika kelas turunan menimpa anggota virtual, anggota itu dipanggil bahkan ketika contoh dari kelas itu sedang diakses sebagai turunan dari kelas dasar." Contoh yang diberikan oleh MSDN hampir sama.
Antony
49

Upcasting (menggunakan (Employee)someInstance) umumnya mudah karena kompilator dapat memberi tahu Anda pada waktu kompilasi jika suatu tipe diturunkan dari yang lain.

Namun downcasting harus dilakukan pada waktu proses secara umum karena kompilator mungkin tidak selalu tahu apakah instance yang dimaksud adalah tipe yang diberikan. C # menyediakan dua operator untuk ini - adalah yang memberitahu Anda jika karya tertunduk, dan kembali benar / salah. Dan seperti yang mencoba melakukan cast dan mengembalikan tipe yang benar jika memungkinkan, atau null jika tidak.

Untuk menguji apakah seorang karyawan adalah seorang manajer:

Employee m = new Manager();
Employee e = new Employee();

if(m is Manager) Console.WriteLine("m is a manager");
if(e is Manager) Console.WriteLine("e is a manager");

Anda juga bisa menggunakan ini

Employee someEmployee = e  as Manager;
    if(someEmployee  != null) Console.WriteLine("someEmployee (e) is a manager");

Employee someEmployee = m  as Manager;
    if(someEmployee  != null) Console.WriteLine("someEmployee (m) is a manager");
Preet Sangha
sumber
11
  • Upcasting adalah operasi yang membuat referensi kelas dasar dari referensi subkelas. (subclass -> superclass) (yaitu Manajer -> Karyawan)
  • Downcasting adalah operasi yang membuat referensi subclass dari referensi kelas dasar. (superclass -> subclass) (yaitu Karyawan -> Manajer)

Dalam kasus Anda

Employee emp = (Employee)mgr; //mgr is Manager

Anda sedang melakukan upcasting.

Upcast selalu berhasil tidak seperti downcast yang membutuhkan cast eksplisit karena berpotensi gagal saat runtime. ( InvalidCastException ).

C # menawarkan dua operator untuk menghindari pengecualian ini dilemparkan:

Mulai dari:

Employee e = new Employee();

Pertama:

Manager m = e as Manager; // if downcast fails m is null; no exception thrown

Kedua:

if (e is Manager){...} // the predicate is false if the downcast is not possible 

Peringatan : Ketika Anda melakukan upcast, Anda hanya dapat mengakses metode superclass, properti dll ...

pemenang
sumber
6

Jika Anda perlu memeriksa setiap objek Karyawan apakah itu objek Manajer, gunakan metode OfType:

List<Employee> employees = new List<Employee>();

//Code to add some Employee or Manager objects..

var onlyManagers = employees.OfType<Manager>();

foreach (Manager m in onlyManagers) {
  // Do Manager specific thing..
}
HOKBONG
sumber
2

Jawaban 1: Ya namanya upcasting tapi cara melakukannya bukan cara modern. Upcasting dapat dilakukan secara implisit, Anda tidak memerlukan konversi apa pun. Jadi tinggal tulisan Emp = mgr; cukup untuk upcasting.

Jawaban 2: Jika Anda membuat objek kelas Manajer, kita dapat mengatakan bahwa manajer adalah seorang karyawan. Karena Manajer Kelas: Karyawan menggambarkan hubungan Is-A antara Kelas Karyawan dan Kelas Manajer. Jadi dapat dikatakan bahwa setiap manajer adalah seorang karyawan.

Tetapi jika kita membuat objek kelas Karyawan, kita tidak dapat mengatakan bahwa karyawan ini adalah manajer karena kelas Karyawan adalah kelas yang tidak mewarisi kelas lain. Jadi Anda tidak bisa langsung men-downcast objek Kelas Karyawan ke objek Kelas Manajer.

Jadi jawabannya adalah, jika Anda ingin downcast dari objek Kelas Karyawan ke objek Kelas Manajer, pertama-tama Anda harus memiliki objek Kelas Manajer terlebih dahulu baru Anda dapat men-downcastnya.

Asad Patel
sumber
-1

Upcasting dan Downcasting:

Upcasting: Casting dari Derived-Class ke Base Class Downcasting: Casting dari Base Class ke Derived Class

Mari kita pahami sama seperti contoh:

Pertimbangkan dua kelas Shape as My parent class dan Circle as a Derived class, yang didefinisikan sebagai berikut:

class Shape
{
    public int Width { get; set; }
    public int Height { get; set; }
}

class Circle : Shape
{
    public int Radius { get; set; }
    public bool FillColor { get; set; }
}

Upcasting:

Bentuk s = Bentuk baru ();

Lingkaran c = s;

Baik c dan s merujuk ke lokasi memori yang sama, tetapi keduanya memiliki tampilan yang berbeda, yaitu menggunakan referensi "c", Anda dapat mengakses semua properti kelas dasar dan kelas turunan juga, tetapi menggunakan referensi "s" Anda dapat mengakses properti dari satu-satunya kelas induk.

Contoh praktis upcasting adalah kelas Stream yang merupakan kelas dasar dari semua jenis pembaca aliran kerangka .net:

Pembaca StreamReader = StreamReader baru (FileStreamReader baru ());

di sini, FileStreamReader () diubah menjadi streadm reder.

Downcasting:

Bentuk s = Lingkaran baru (); di sini seperti yang dijelaskan di atas, view of s adalah satu-satunya parent, untuk membuatnya baik untuk parent maupun child kita perlu downcast nya

var c = (Lingkaran) s;

Contoh praktis dari Downcasting adalah kelas tombol WPF.

AutomationNerd
sumber