2013-05-14 11 views
5

W języku C# klasa A zawiera publiczną metodę Foo(), która wykonuje pewne przetwarzanie i zwraca wartość. protected metoda Bar(), również w klasie A wykonuje tę samą logikę co Foo(), po której następuje dodatkowe przetwarzanie, a następnie zwraca wartość.Metoda wywołania podstawowego zamiast zastąpienia

Aby uniknąć powielania kodu, Bar() wywołuje Foo() i używa zwrotu jako wartości pośredniej.

class A 
{ 
    public virtual String Foo() 
    { 
    String computedValue; 
    // Compute the value. 
    return computedValue; 
    } 

    protected String Bar() 
    { 
    String computedValue; 
    String intermediateValue = Foo(); 
    /// More processing to create computedValue from intermediateValue. 
    return computedValue; 
    } 
} 

Klasa B dziedziczy z A i nadpisuje Foo(). Zastąpienie wywołuje implementację klasy podstawowej Bar().

class B : A 
{ 
    public override String Foo() 
    { 
    base.Bar(); 
    } 
} 

To (oczywiście) przechodzi w nieskończoną pętlę, aż do wyczerpania pamięci komputera, a następnie wygeneruje wyjątek przepełnienia stosu.

Najbardziej oczywistym rozwiązaniem jest przepisanie A za pomocą prywatnej metody FooInternals, która zawiera odwagę Foo. Foo i Bar są następnie modyfikowane, aby wykorzystać wyniki tej metody.

Czy istnieje sposób na wymuszenie A Bar() na wywołanie A Foo() zamiast przesłonięcia?

(jestem prawie na pewno jest zbyt mądry tutaj; to idzie całkowicie przeciwko polimorfizmu Ale nie mogę oprzeć się pokusie, aby spróbować popychając moją wiedzę nieco dalej..)

Odpowiedz

7

Czy istnieje sposób zmusić A Bar() do wywołania A's Foo() zamiast override?

Nie bezpośrednio. Najprostszym refaktoring byłoby zmienić Foo do:

public virtual string Foo() 
{ 
    return FooImpl(); 
} 

private string FooImpl() 
{ 
    String computedValue; 
    // Compute the value. 
    return computedValue; 
} 

Następnie zmień Bar zadzwonić FooImpl zamiast Foo.

(To jest chyba to, co masz na myśli w swoim „najbardziej oczywiste rozwiązanie” pkt. - której brakowało mi w pierwszym czytaniu, boję)

Zasadniczo jest to tylko jeden z tych obszarów, w których dziedziczenie jest problematyczne . Gdy jedna metoda wirtualna wywołuje inną, musi być udokumentowana, aby podklasy mogły uniknąć problemów - nawet jeśli wydaje się, że to jest szczegół implementacji. To właśnie sprawia, że ​​wolę kompozycję niż dziedziczenie - oczywiście, gdy obie są rozsądnymi opcjami.

+0

Dzięki, pomyślałem, że to było najlepsze/oczywiste podejście. Zastanawiam się, czy nie przeoczyłem alternatywy. – ThatBlairGuy

+1

@ThatBlairGuy: Przepraszam, udało mi się ominąć akapit w twojej odpowiedzi, który to opisuje. Ups :) Ale nie, to wszystko, co możesz zrobić naprawdę. –

+0

Bez obaw, dziękuję za weryfikację, że czegoś nie przeoczyłem. – ThatBlairGuy

Powiązane problemy