aşağı ve yukarı


88

Ben yeniyim C # (ve OOP ). Aşağıdaki gibi bir kodum olduğunda:

class Employee
{
    // some code
}


class Manager : Employee
{
    //some code
}

Soru 1 : Bunu yapan başka bir kodum varsa:

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

İşte Employeebir Manager, ama onu böyle bir Employeeşeye çevirdiğimde, bu onu yukarı dökümlediğim anlamına mı geliyor?

Soru 2 :

Birkaç Employeesınıf nesnesine sahip olduğumda ve hepsi olmasa da bazıları nesneye Managersahipse, onları mümkün olan yerlerde nasıl indirebilirim?


6
Yukarı yayın, açık döküm olmadan yapılabilir. Bu yüzden Employee emp= mgr;yeterli olmalı.
koltuk

Yanıtlar:


95
  1. Bu doğru. Bunu yaptığınızda, onu bir employeenesneye atmış olursunuz, bu, yöneticiye özgü hiçbir şeye erişemeyeceğiniz anlamına gelir.

  2. Downcasting, temel bir sınıfı alıp daha sonra onu daha spesifik bir sınıfa dönüştürmeye çalıştığınız yerdir. Bu, is ve aşağıdaki gibi açık bir döküm kullanılarak başarılabilir:

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

veya şu asoperatörle:

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

Net olmayan bir şey varsa, düzeltmekten memnuniyet duyarım!


Downcasting nedir bilmek için bir örneğe ihtiyacım var?
user184805

4
Yerleşik terimleri yeniden tanımlamaktan kaçının: OOP ve C # bağlamında "kutu", oldukça farklı bir anlama gelir (= bir değer türü nesneyi bir referansa sarmak). Ayrıca, örneğiniz asyerine işleci kullanabilir (ve kullanmalıdır) is, ardından bir atama.
Konrad Rudolph

2
İlk noktada düzeltildim ve cevabımın ikinci yarısını her iki yolu da gösterecek şekilde değiştirdim.
RCIX

3
İlk ifadeniz ("... [Yönetici sınıfının bir örneğini] bir" çalışan "nesnesine [..] çevirmek, yöneticiye özgü hiçbir şeye erişemeyeceğiniz anlamına gelir") tamamen doğru değildir. OP'nin örneğinde, Çalışan, Yönetici'de geçersiz kılınan bir sanal üyeye sahipse, CLR, atamadan bağımsız olarak Yönetici uygulamasını çağıracaktır. C # 'da polimorfizm hakkındaki MSDN makalesinden: "Türetilmiş bir sınıf sanal bir üyeyi geçersiz kıldığında, bu üye, bu sınıfın bir örneğine temel sınıfın bir örneği olarak erişildiğinde bile çağrılır." MSDN tarafından sağlanan örnek neredeyse aynıdır.
Antony

49

Upcasting (kullanmak (Employee)someInstance) genellikle kolaydır, çünkü derleyici size derleme zamanında bir tipin diğerinden türetilip türetilmediğini söyleyebilir.

Ancak, derleyici söz konusu örneğin belirtilen tipte olup olmadığını her zaman bilemeyebileceğinden, genel olarak aşağı yayınlama işlemi çalışma zamanında yapılmalıdır. C # Bunun iki operatörlerine - olduğu mahzun eser olmadığını gösteren, hangi ve doğru / yanlış döndürür. Ve olarak hangi girişimleri cast yapmak ve doğru türü mümkünse veya null değilse döner etmek.

Bir çalışanın yönetici olup olmadığını test etmek için:

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");

Bunu da kullanabilirsiniz

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");

11
  • Yukarı çevrim , bir alt sınıf referansından temel bir sınıf referansı oluşturan bir işlemdir. (alt sınıf -> üst sınıf) (yani Yönetici -> Çalışan)
  • Aşağı yayın , temel sınıf referansından bir alt sınıf referansı oluşturan bir işlemdir. (süper sınıf -> alt sınıf) (yani Çalışan -> Yönetici)

Senin durumunda

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

bir yukarı döküm yapıyorsun.

Bir yukarı yayın, çalışma zamanında potansiyel olarak başarısız olabileceğinden, açık bir atama gerektiren aşağı yayının aksine her zaman başarılı olur. ( InvalidCastException ).

C #, bu istisnanın atılmasını önlemek için iki operatör sunar:

Den başlayarak:

Employee e = new Employee();

İlk:

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

İkinci:

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

Uyarı : Yukarı yayın yaptığınızda yalnızca üst sınıfın yöntemlerine, özelliklerine vb. Erişebilirsiniz.


6

Employee nesnelerinin her birinin bir Manager nesnesi olup olmadığını kontrol etmeniz gerekirse, OfType yöntemini kullanın:

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..
}

2

Cevap 1: Evet buna yukarı yayınlama denir ama bunu yapma şekliniz modern bir yöntem değil. Upcasting dolaylı olarak gerçekleştirilebilir, herhangi bir dönüşüme ihtiyacınız yoktur. Yani sadece Employee emp = mgr yazarak ; upcasting için yeterlidir.

Cevap 2: Yönetici sınıfının nesnesini oluşturursanız, yöneticinin bir çalışan olduğunu söyleyebiliriz. Çünkü sınıf Yöneticisi: Çalışan , Çalışan Sınıfı ile Yönetici Sınıfı arasındaki Is-A ilişkisini gösterir . Yani her yöneticinin bir çalışan olduğunu söyleyebiliriz.

Ancak Employee sınıfının nesnesini oluşturursak, bu çalışanın yönetici olduğunu söyleyemeyiz çünkü sınıf Çalışan başka herhangi bir sınıfı miras almayan bir sınıftır. Bu nedenle, bu Çalışan Sınıfı nesnesini Yönetici Sınıfı nesnesine doğrudan indiremezsiniz.

Öyleyse cevap, Çalışan Sınıfı nesnesinden Yönetici Sınıfı nesnesine aşağı yayın yapmak istiyorsanız, önce Yönetici Sınıfı nesnesine sahip olmalısınız, sonra onu yukarı doğru çevirebilir ve sonra onu aşağıya çevirebilirsiniz.


-1

Upcasting ve Downcasting:

Upcasting: Türetilmiş Sınıftan Temel Sınıfa Döküm: Temel Sınıftan Türetilmiş Sınıfa Döküm

Aynı şeyi bir örnekle anlayalım:

Shape olarak iki sınıfı, My parent sınıfı olarak ve Circle'ı da Türetilmiş bir sınıf olarak aşağıdaki gibi tanımlayın:

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:

Şekil s = yeni Şekil ();

Daire c = s;

Hem c hem de s aynı bellek konumuna başvuruyor, ancak her ikisinin de farklı görünümleri var, yani "c" referansını kullanarak temel sınıfın ve türetilmiş sınıfın tüm özelliklerine erişebilirsiniz, ancak "s" referansını kullanarak özelliklere erişebilirsiniz. tek ebeveyn sınıfının.

Yukarı yayınlamanın pratik bir örneği, .net çerçevesinin tüm akış okuyucu türlerinin temel sınıfı olan Stream sınıfıdır:

StreamReader okuyucu = new StreamReader (yeni FileStreamReader ());

burada, FileStreamReader () streadm rederine yükseltilir.

Downcasting:

Şekil s = yeni Daire (); burada yukarıda açıklandığı gibi, s'nin görünümü tek ebeveyndir, bunu hem ebeveyn hem de çocuk için yapmak için onu aşağıya indirmemiz gerekir.

var c = (Daire) s;

Downcasting'in pratik örneği, WPF'nin düğme sınıfıdır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.