2013-05-14 5 views
5

In C#, la classe A contiene un metodo pubblico Foo() che esegue qualche elaborazione e restituisce un valore. protected metodo Bar(), anche nella classe A esegue la stessa logica di Foo(), seguita da un'ulteriore elaborazione e quindi restituisce un valore.Metodo call base anziché override

Per evitare la duplicazione del codice, Bar() chiama Foo() e utilizza il reso come valore intermedio.

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; 
    } 
} 

Classe B eredita da A e sostituisce Foo(). L'override chiama l'implementazione della classe base di Bar().

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

questo (ovviamente) entra in un ciclo infinito finché il computer esaurisce la memoria e poi produce un'eccezione di overflow dello stack.

La soluzione più ovvia è riscrivere A con un metodo privato FooInternals che contiene il coraggio di Foo. Foo e Bar vengono quindi modificati per utilizzare i risultati di tale metodo.

C'è un modo per forzare A's Bar() per chiamare A Foo() anziché l'override?

(sono quasi certamente essendo troppo intelligente qui; questa va completamente contro il polimorfismo ma non riesco a resistere alla tentazione di provare a spingere un po 'oltre la mia conoscenza..)

risposta

7

c'è un modo forzare A's Bar() per chiamare A's Foo() al posto di override?

Non direttamente. Il refactoring semplice sarebbe quella di cambiare Foo a:

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

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

poi cambiare Bar chiamare FooImpl invece di Foo.

(Questo è probabilmente ciò che si intende nel vostro paragrafo "soluzione più ovvia." -, che ho perso in prima lettura, temo)

Fondamentalmente questo è solo uno di quei settori in cui l'ereditarietà è problematica . Quando un metodo virtuale ne chiama un altro, è necessario documentarlo in modo che le sottoclassi possano evitare di causare problemi, anche se sembra che lo sia un dettaglio di implementazione. È questo genere di cose che mi fa preferire la composizione all'eredità - dove entrambe sono opzioni ragionevoli, naturalmente.

+0

Grazie, ho capito che era l'approccio migliore/ovvio. Mi stavo solo chiedendo se avrei potuto perdere un'alternativa. – ThatBlairGuy

+1

@ThatBlairGuy: Siamo spiacenti, sono riuscito a saltare il paragrafo nella tua risposta che lo descrive. Oops :) Ma no, questo è tutto quello che puoi fare davvero. –

+0

Nessun problema, grazie per aver verificato che non stavo trascurando qualcosa. – ThatBlairGuy