2013-05-24 25 views
7

mam klasy z niektórych funkcji wirtualnych, udawajmy jest to jeden z nich:Zastępowanie metody wirtualne, gdy instancji klasy

public class AClassWhatever 
{ 
    protected virtual string DoAThingToAString(string inputString) 
    { 
     return inputString + "blah"; 
    } 
} 

chcę instancję tej klasy podczas nadrzędnymi „DoAThingToAString” inline, podobnie jak I można zadeklarować właściwości inline w deklaracji, w następujący sposób:

... 

AClassWhatever instance = new AClassWhatever 
{ 
    DoAThingToAString = new function(string inputString) 
    { 
     return inputString + inputString + " fill my eyes." 
    } 
} 

... 

a teraz „przykład”, DoAThingToAString jest przesłonięta z tej definicji. Muszę być w stanie zdefiniować domyślne zachowanie w definicji klasy i tylko przesłonić go w razie potrzeby, inaczej różne czasy i nie chcę proliferować pęczku podklas, aby to zrobić.

Wiem, że potrzebuję korzystać z delegatów lub czegoś podobnego, ale byłem poza grą składni zbyt długo, a Google dawało mi zbyt wiele nieistotnych informacji.

Odpowiedz

6

Możesz użyć delegatów lub Func s, aby to zrobić.

pierwsze, dodać do swojej klasy AClassWhatever:

public Func<string, string> DoAThingToAString = (x) => x + "blah"; 

Teraz można użyć tej samej składni, aby zastąpić działanie.

AClassWhatever instance = new AClassWhatever() 
{ 
    DoAThingToAString = (x) => x + x + " fill my eyes." 
}; 
+0

To składnia byłem szukam, ale głupie pytanie. W DoAThingToAString używam metody rozszerzania kontrolera, która jest wywoływana z działania kontrolera jako takiego: 'this.DoExtensionMethod (someString);' Nie mam już odniesienia do "tego" teraz, gdy jestem w Func definicja. Czy istnieje sposób na uzyskanie odniesienia do osoby dzwoniącej lub czy muszę przekazać ją razem z innymi danymi wejściowymi? – kamii

+2

@kamii, Będziesz musiał przekazać odniesienie do obiektu lub inne określone wartości, których potrzebujesz. Jest to funkcja anonimowa, więc nie ma pojęcia o instancji. (proszę sprawdzić fakt). – gunr2171

5

Nie można tego zrobić za pomocą metod, ale można zrobić odpowiednik z delegatami/metod anonimowych:

public class AClassWhatever 
{ 
    public AClassWhatever() 
    { 
     this.DoAThingToAString = this.DoAThingToAStringImpl; 
    } 

    public Func<string, string> DoAThingToAString { get; set; } 

    protected virtual string DoAThingToAStringImpl(string input) 
    { 
     return input + input + " fill my eyes."; 
    } 
} 

Zastosowanie:

var instance = new AClassWhatever 
{ 
    DoAThingToAString = inputString => inputString + inputString + 
     " fill my eyes something other than the default behavior." 
} 

var result = instance.DoAThingToAString("input"); 

Zauważ, że inputString => inputString + inputString + "..." jest taka sama jako x => x + x + "..."

+0

"Muszę umieć zdefiniować domyślne zachowanie w definicji klasy ..." – mellamokb

+0

@mellamokb Zmieniłem swoją odpowiedź, aby zapewnić domyślną implementację w konstruktorze. – Dan

+0

Daję ci odpowiedź ze względu na lepsze kodowanie, ale być może masz odpowiedź na pytanie referencyjne, o które poprosiłem gunr2171 w komentarzach? – kamii

0

Dlaczego nie zdefiniować właściwości delegata i użyć tej definicji, jeśli istnieje, gdy wywoływana jest metoda? Podczas tworzenia obiektu można podać alternatywną definicję za pomocą właściwości.

Na przykład:

public MyDelegateTypeThatMatchesMyFunctionCall DoAThingToAStringProperty { get; set; } 

public class AClassWhatever 
{ 
    protected virtual string DoAThingToAString(string inputString) 
    { 
     var handler = this.DoAThingToAStringProperty; 
     if (handler) 
     { 
      return handler(inputString); 
     } 

     // do default behavior 
     return inputString + "blah"; 
    } 
} 

Jeśli chcesz mieć pewność, że Twoja nieruchomość delegat zastępuje dowolny zastąpiona definicję metody wirtualnej można zrobić to tak:

public MyDelegateTypeThatMatchesMyFunctionCall DoAThingToAStringProperty { get; set; } 

public class AClassWhatever 
{ 
    protected string DoAThingToAString(string inputString) 
    { 
     var handler = this.DoAThingToAStringProperty; 
     if (handler) 
     { 
      return handler(inputString); 
     } 

     // do default behavior 
     return DoAThingToAStringInternal(inputString); 
    } 

    protected virtual string DoAThingToAStringInternal(string inputString) 
    { 
     // do default behavior 
     return inputString + "blah"; 
    } 
} 
Powiązane problemy