2015-07-28 20 views
11

Aşağıdaki kodum var.Çocuk sınıfı nesnesini neden üst sınıf referans değişkenine ataıyoruz?

public class Parent 
{ 
    public void Print() 
    { 
     Console.WriteLine ("Parent Method"); 
    } 
} 

public class Child : Parent 
{ 
    public new void Print() 
    { 
     Console.WriteLine ("Child Method"); 
    } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     Child C = new Child(); 
     C.Print(); 
    } 
} 

Bu kodu çalıştırırsanız, ben "Çocuk Yöntemi" sonuç almak Ama aşağıdakileri yaparsanız, neden sonuç "Veli Yöntemi" alırım? Ben new Child() biz Child sınıfın örneğini oluşturmak demektir düşünce

Child C = new Child(); 
Parent P = new Child(); 

aşağıda

public class Parent 
{ 
    public void Print() 
    { 
     Console.WriteLine ("Parent Method"); 
    } 
} 

public class Child : Parent 
{ 
    public new void Print() 
    { 
     Console.WriteLine ("Child Method"); 
    } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     Parent P = new Child(); // The only difference is this. 
     P.Print(); 
    } 
} 

tek farktır. Ve ben her ikisi de, C ve P, yalnızca Child sınıfının örneğinin konumunu tutan nesne başvuru değişkenleri olduğunu düşündüm.
Yanlış mıyım, yoksa bir şey mi özlediğimi söyler misin, çünkü yukarıdaki durumlarda neden farklı sonuçlar aldığımı anlamıyorum.

+3

bunları geçersiz kılma değil, yöntemler saklandıkları çünkü. P.Print yazdığınızda, derleyici gizli alt yöntemi değil, yalnızca ebeveyn yazdırma yöntemini çağırabilir. –

+0

Olası kopya: http://stackoverflow.com/questions/17717570/why-does-calling-a-method-in-my-derived-class-call-the-base-class-method –

+0

Bir kenara tavsiye ederim yasal olarak gerekmedikçe yöntem gizleme kaçınmak. Kodun sürdürülmesi zorlaşır. Eric Lippert'in [Metod Gizleme Metodolojisi] 'ni alıntılamak (http://blogs.msdn.com/b/ericlippert/archive/2008/05/21/method-hiding-apologia.aspx), "Türetilmiş türlerin sözleşmeleri kırdığı görülüyor Eğer bir tür D tipi taban sınıfı B üzerinde bir metod M gizlerse, çünkü DM, BM'den farklı bir şey yapar, farklı bir ismi olmamalıdır? " – Brian

cevap

19

Bu, yöntemini Child'da yeniden bildirdiğinizden kaynaklanıyor. Yani derleme zamanında P.Print(), Parent.Print'a gider, ancak C.Print(), Child.Print()'a gider. Eğer yerine Child yılında geçersiz bir sanal yöntem olsaydı ikisi de baskı "Çocuk Yöntemi" diye:

public class Parent 
{ 
    // Declare this as virtual, allowing it to be overridden in 
    // derived classes. The implementation will depend on the 
    // execution-time type of the object it's called on. 
    public virtual void Print() 
    { 
     Console.WriteLine ("Parent Method"); 
    } 
} 

public class Child : Parent 
{ 
    // Override Parent.Print, so if Print is called on a reference 
    // with compile-time type of Parent, but at execution it 
    // refers to a Child, this implementation will be executed. 
    public override void Print() 
    { 
     Console.WriteLine ("Child Method"); 
    } 
} 

İlgili: MSDN üzerinde

0

P türünü Parent olarak bildirdiğinizden. Bir Child atayınca, bu türe dönüştürülecek.

4

01 yanayöntemi, virtual değil, derleyici CLR'ye gerçek çalışma zamanı türüne göre yöntemi çağırmak için kod yaymayacak.

Yani, değişkeniniz Child olarak adlandırıldığında, Child.Print çağrılır. Ancak, ona Parent olarak başvurduğunuzda, Parent.Print kullanılacaktır.

Burada tek gölgelendirme içindir new anahtar kelime kullanımı çocuk yöntem aslında geçersiz kılma ana yöntem olup gizliyor derleyici söyleme ama başka türlü hiçbir etkisi yoktur için.

1

JCronin, Ana Pentle P = new Child() atarsınız. Çocuk sınıfı davranışını elde etmek için, onu bir Çocuğa (var x = (Çocuk) P) geri döndürmeniz veya Çocuk örneği örneğini (Çocuk P = yeni Çocuk()) oluşturmanız gerekir.

Burada yöntemleri saklıyorsun Çünkü kaputun

Child C = new Child(); 
C.Print(); 

altında ne olduğudur Downcasting

8

Bkz onları geçersiz kılma değil. Ebeveyn olarak yazdırma yöntemi gizli ve Child.Print() çağrılır.

Parent P = new Child(); // The only difference is this. 
P.Print(); 

Bu

enter image description here

(Yeni Çocuk()) bir Veli tipi Referans üzerinde çağrılır. Eğer bu bir denerseniz

enter image description here

, Veli tip referans Çocuk tipine döküm edilecektir. Bundan böyle Child.Print() çağrılır.

Parent P = new Child(); 
((Child)P).Print(); 

enter image description here

çıkışı olacaktır: Çocuk Yöntem

+0

Cevabınız için teşekkür ederim ama bana ne olduklarını söyleyebilir misiniz? – JCronin

+0

@JCronin onlar CIL. CIL düşük seviyeli bir dildir. Temel olarak kodunuzu derlediğinizde, ara dil (IL) olarak derlenecek ve aynı zamanda MSIL (Microsoft Intermediate Language) olarak da adlandırılacaktır. IL kodunu https://msdn.microsoft.com/en-us/library/f7dy01k1(v=vs.110).aspx BTW kullanarak görebilir, IL kodunu almak için LINQPad kullandım. buradan kontrol edebilirsiniz https://www.linqpad.net/ – yantaq

İlgili konular