2013-05-04 23 views
5

Aradığım ve sorunum için herhangi bir çözüm bulamadık. Benim senaryo çok basit:base.Method() birden fazla miras düzeyiyle çağrılmıyor mu?

public class A 
{ 
    public virtual void MethodOne() 
    { 
     Console.log("A"); 
    } 
} 

public class B : A 
{ 
    public override void MethodOne() 
    { 
     base.MethodOne(); 
     Console.log("B"); 
    } 
} 

public class C : B 
{ 
    public override void MethodOne() 
    { 
     base.MethodOne(); 
     Console.log("C"); 
    } 
} 

Ne yapmaya çalışıyorum sınıf C bir örneğini (biz 'instanceC' adını vereceğiz) geçersiz kılınan üst biriminin yöntemi ve bunun büyükbaba hem çağrı olması.

instanceC.MethodOne(); 
// Output: 
// "A" 
// "B" 
// "C" 

Ama bunun yerine bu alıyorum: Yani bu beklediğiniz sınıf B yöntemi ile

instanceC.MethodOne(); 
// Output 
// "A" 
// "C" 

üzerinden atlanır ediliyor. Bu mümkün değil mi? Bunun bütün kalıtım/polimorfizm noktası olduğunu düşündüm. Şimdiden teşekkürler!

+6

C'nin B'den türetilmediğinden ve A'nın değil mi olduğundan emin misiniz? – jure

+0

Neden C ovveride B'den geliyor? A. – Derek

+10

'dan miras almasını istiyorsun Sizin örneğiniz benim için beklendiği gibi çalışıyor ve 'ABC' – Lee

cevap

10

Örneğiniz benim için beklendiği gibi çalışıyor. A B'yi görüyorum. En olası sorununun C'nin B'yi uzatmaması olduğunu düşünüyorum. Ancak, konu üzerinde çalışırken daha güvenli bir model önereyim. MethodOne'un tüm geçersiz kılmaları temel sınıflarından kod yürütmesini istiyor görünüyorsunuz. Büyük, miras, bunun için iyi bir modeldir. Bununla birlikte, bu modelde mirasçıları temel mantığı yürütmeye zorlayamazsınız, çünkü onları base.MethodOne() numaralı telefonu aramaya zorlayamazsınız. base.MethodOne() numaralı telefonu arayarak bile mantığın sırasını sağlayamazsınız. Yöntemin başlangıcında, yöntemin ortası veya yöntemin sonu olarak base.MethodOne()'u arayacaklar mı? Çoğu zaman, bu tür kalıplarda alt sınıfların işlevin başında tüm temel mantığı yürütmesini istersiniz. Aşağıdaki model, mirasçıların sipariş temel sınıflarında temel mantığı yürütmesini beklemektedir. Teknik olarak daha az esnek ama daha güvenlidir çünkü mirasçılar temel sınıfları temel sınıfların belirttiği şekilde genişletmelidir.

public class A 
{ 
    //Don't make this method virtual because you don't actually want inheritors 
    //to be able to override this functionality. Instead, you want inheritors 
    //to be able to append to this functionality. 
    public void MethodOne() 
    { 
     Console.WriteLine("A"); 
     MethodToBeOverriddenOne(); 
    } 
    //Expose a place where inheritors can add extra functionality 
    protected virtual void MethodToBeOverriddenOne() { }  
} 

public class B : A 
{ 
    //Seal the method because you don't actually want inheritors 
    //to be able to override this functionality. Instead, you want inheritors 
    //to be able to append to this functionality. 
    protected sealed override void MethodToBeOverriddenOne() 
    { 
     Console.WriteLine("B"); 
     MethodToBeOverriddenTwo(); 
    } 
    //Expose a place where inheritors can add extra functionality 
    protected virtual void MethodToBeOverriddenTwo() { } 
} 

public class C : B 
{ 
    protected sealed override void MethodToBeOverriddenTwo() 
    { 
     Console.WriteLine("C"); 
    } 
} 
+1

Bu, temel yöntemlerin her zaman nasıl çağrıldığını açıkça gösterdiği için diğerinden daha iyi bir yanıttır. Neden reddedildiğinin hiçbir fikri yok. – Andy

+0

Çok uykum var ve siz haklısınız; C aptalca C yerine A'yı uzatıyordu. Bu gerçekten sorun olsa da, bunun daha iyi bir çözüm olduğunu düşünüyorum ve iyi sonuçlara sahibim. Teşekkür ederim! – helios

+0

Ben downvoting, benim de daha iyi olduğunu düşündüm ve bunu bir +1 –

1

Gönderdiğiniz örnek mükemmel çalışıyor, gerçek kodunuzda ne yapıyor olursanız yazdığınızdan farklı. İstediğiniz gibi çalışarak

Here is your code running on ideone.

using System; 

public class Test 
{ 
     public static void Main() 
     { 
       var c = new C(); 
       c.MethodOne(); 
     } 
} 

public class A 
{ 
    public virtual void MethodOne() 
    { 
     Console.WriteLine("A"); 
    } 
} 

public class B : A 
{ 
    public override void MethodOne() 
    { 
     base.MethodOne(); 
     Console.WriteLine("B"); 
    } 
} 

public class C : B 
{ 
    public override void MethodOne() 
    { 
     base.MethodOne(); 
     Console.WriteLine("C"); 
    } 
} 
İlgili konular