2016-04-07 6 views
1
public abstract class Beverage 
{ 
    public string description = "Unknown Beverage"; 
    public string GetDescription() 
    { 
     return description; 
    } 
} 

public abstract class CondimentDecorator : Beverage 
{ 
    public abstract new string GetDescription(); 
} 


public class Espresso : Beverage 
{ 
    public Espresso() 
    { 
     description = "Espresso"; 
    } 

class Mocha : CondimentDecorator 
{ 

    Beverage beverage; 

    public Mocha(Beverage beverage) 
    { 
     this.beverage = beverage; 
    } 
    public override string GetDescription() 
    { 
     return beverage.GetDescription() + ", Mocha"; 
    } 

kullanıyor. Şimdi kod beklendiği gibi yürütür bileşim kullanılmadan örneğini ve açıklama döndürdüğünde Espresso: I bileşimi kullandığınızda, içecek temel sınıfından içecek açıklama alanı erişildiğinde, ancakC# bileşimin anlamaya çalışırken, ama sargı nesneler temel sınıf alan erişme yerine espresso bileşeni olması amaçlanmıştır ve Mocha sargı olması amaçlanmıştır türetilmiş uygulama

static void Main(string[] args) 
    { 
     Beverage beverage = new Espresso(); 
     Console.WriteLine(beverage.GetDescription()); 

Output: Espresso 

ve program döndürür Açıklama "Bilinmeyen İçecek." "Espresso, Mocha" Beverage yılında GetDescription yöntemi sanal değilse da ondan

Beverage beverage2 = new Espresso(); 

     beverage2 = new Mocha(beverage2); 

     Console.WriteLine(beverage2.GetDescription()); 
+0

Neden soyut yöntem beyanında 'new' anahtar sözcüğünü kullanıyorsunuz? – kai

+1

da, "sanal" veya "soyut" olmadığı sürece C# içindeki bir yöntemi geçersiz kılabilirsiniz. 'Beverage.GetDescription()' da değildir. – kai

+0

Bunu daha açık bir şekilde açıklayan yazıyı bulamıyorum, ancak sol tarafta “İçecek” türünü seçmeniz gerektiğini düşünüyorum, bu yüzden “beverage2.GetDescription()” ifadesini çağırmak sadece temel sınıflar yöntemini çağırır. Muhtemelen bunu yapmak zorundasınız, Console.WriteLine (((Mocha) beverage2) .GetDescription()); – Quantic

cevap

0

: Ancak, ben çıkışını bekliyorum. beverage.GetDescription() yazdığınızda, derleyici bakar ve beverage türünün Beverage olduğunu görür ve daha sonra sanal olmayan bir GetDescription yöntemi olduğunu görür. Sanal olmadığından, türetilen GetDescription çağrılmıyor.

Ne istiyorsun Bunun gibi daha bir şeydir:

public abstract class Beverage 
{ 
    public string description = "Unknown Beverage"; 
    public virtual string GetDescription() 
    { 
     return description; 
    } 
} 

public abstract class CondimentDecorator : Beverage 
{ 
    public override string GetDescription() 
    { 
     return GetDescriptionOverride(); 
    } 

    protected abstract string GetDescriptionOverride(); 
} 
Bir sınıf sanal işlevi (veya yöntem) birçok derleyici bir dizi işaret sınıfa gizli üye değişkeni eklemek tanımlar zaman
0

sanal yöntem tablosu (VMT veya Vtable) olarak adlandırılan (sanal) işlevlere işaretçiler. Bu işaretçiler, uygun işlev uygulamalarını çağırmak için çalışma zamanında kullanılır, çünkü derleme zamanında, temel işlev çağrılacaksa veya temel sınıftan miras alınan bir sınıf tarafından uygulanan türetilmiş bir yöntemle henüz bilinemeyebilir. Virtual method table

@kai sorunu işaret etti. Yöntemin sanal olarak tanımlanması gerekir. Daha sonra çalışma zamanı, bu durumda Moccha olan çalışma zamanı türü için bir geçersiz kılma yöntemini aramayı bilir. Ayrıca, CondimentDecorator soyut ise, tekrar CondimentDecorator'ı yeniden tanımlamaya gerek yoktur.

public abstract class Beverage 
{ 
    public string description = "Unknown Beverage"; 
    public virtual string GetDescription() 
    { 
     return description; 
    } 
} 

public abstract class CondimentDecorator : Beverage 
{ 

} 

//no change to the rest 
... 

bunu yapın ve size gördüğünüz yerde, İkinci örnekte temel sınıf

public abstract new string GetDescription(); 

üzerine GetDescription yöntemi saklıyorsun aşağıdaki satırı ile çıkış

"Espresso, Mocha" 
0

göreceksiniz Sorun, değişkeni İçecek olarak yazıyorsunuz. Bu nedenle, temel sınıftaki yöntemi çağırmakla bitiyorsunuz. Basit bir örnek olarak

:

public class First 
{ 
    public virtual string GetName() 
    { 
     return "First"; 
    } 
} 

public class Second : First 
{ 
    public override string GetName() 
    { 
     return "Second"; 
    } 
} 

Bunu ikinci iki kere yazdırır bulacaksınız:

public class First 
{ 
    public string GetName() 
    { 
     return "First"; 
    } 
} 

public class Second : First 
{ 
    public new string GetName() 
    { 
     return "Second"; 
    } 
} 

public static class Program 
{ 

    public static void Main(string[] args) 
    { 
     Second second = new Second(); 
     Console.WriteLine(second.GetName()); 
     // Prints "Second" 

     First first = second; 
     Console.WriteLine(first.GetName()); 
     // Prints "First" 

     Console.ReadKey(); 
    } 
} 

Ardından aşağıdaki değişiklik deneyin.

+0

Teşekkür ederim Karle, Kai ve Uyanış Byte, tüm cevaplar çok yararlı. Ve örneğiniz özellikle yardımcı oldu Karle, teşekkürler! –

İlgili konular