2011-11-30 18 views
21

Sto tentando di aggiornare la memoria ma non riesco a trovare le risposte con Google.Converti classe derivata in classe base

public class BaseClass 
{ 
    public virtual void DoSomething() 
    { 
     Trace.Write("base class"); 
    } 
} 

public class DerivedClass : BaseClass 
{ 
    public override void DoSomething() 
    { 
     Trace.Write("derived class"); 
    } 
} 

Se creo un'istanza della classe derivata, come faccio a convertirlo alla sua classe base in modo che quando si chiama DoSomething(), utilizza unico metodo della classe base?

Un cast dinamico chiama ancora metodo sottoposto a override della classe derivata:

DerivedClass dc = new DerivedClass(); 

dc.DoSomething(); 

(dc as BaseClass).DoSomething(); 

uscita: "classe derivata"

+1

tipo di sconfitte lo scopo di eredità, di solito nella vostra esclusione però si sarebbe richiamare manualmente 'base.DoSomething (), ma a meno che tu possa essere in grado di fare qualcosa con la riflessione. –

+0

Ouch, ho pensato che sarebbe stato qualcosa di semplice che ho trascurato. Grazie – Levitikon

+0

possibile duplicato di [Come richiamare (non virtualmente) l'implementazione originale di un metodo virtuale?] (Http://stackoverflow.com/questions/3378010/how-to-invoke-non-virtually-the-original-implementation -di-un-metodo-virtuale) – Ani

risposta

29

Non è possibile - che è del tutto intenzionale, come questo è ciò che il polimorfismo è tutto. Supponiamo che tu abbia una classe derivata che impone certe precondizioni sugli argomenti che passi ad un metodo sovrascritto, al fine di mantenere l'integrità ... non vuoi essere in grado di bypassare quella convalida e corrompere la sua integrità interna.

All'interno della classe stessa si può non virtualmente chiamare base.AnyMethod() (se questo è il metodo che si sta ignorando o no), ma va bene così, perché questa è la classe stessa decidendo di potenzialmente consentire la sua integrità per essere violata - presumibilmente sa cosa vuol dire facendo.

+0

Grazie Jon. Voglio chiarire, mi piace molto e mi affido alle proprietà e ai metodi delle classi derivate per essere in vigore anche quando la classe è castata alla sua classe base. Sarebbe molto bello anche spogliare le classi derivate in determinate condizioni speciali. Sembra una riflessione o una sorta di deep copy è la strada da percorrere. – Levitikon

+0

Siamo sicuri che questa sia la risposta corretta? Sembra che sia possibile chiamare il metodo base se la classe derivata ha utilizzato la nuova parola chiave anziché sostituire un membro virtuale della classe base. – winnicki

+0

@winnicki: A quel punto non è la stessa situazione della domanda. Potresti chiamare il metodo della classe base se non hai affatto il metodo della classe derivata, o se aveva un nome diverso, o un numero diverso di parametri, ecc ... –

3

Provare a utilizzare il keywor new anziché override Per quanto ne so, questo dovrebbe consentire il comportamento desiderato. Non ne sono davvero sicuro, quindi per favore non incolpare me se sbaglio!

public class BaseClass 
{ 
    public virtual void DoSomething() 
    { 
     Trace.Write("base class"); 
    } 
} 

public class DerivedClass : BaseClass 
{ 
    public new void DoSomething() 
    { 
     Trace.Write("derived class"); 
    } 
} 
7

Si può assolutamente (chiamare il metodo di base), basta leggere su Polimorfismo:

http://msdn.microsoft.com/en-us/library/ms173152(v=VS.80).aspx

Esempio:

public class BaseClass 
{ 
    public void DoWork() { } 
    public int WorkField; 
    public int WorkProperty 
    { 
     get { return 0; } 
    } 
} 

public class DerivedClass : BaseClass 
{ 
    public new void DoWork() { } 
    public new int WorkField; 
    public new int WorkProperty 
    { 
     get { return 0; } 
    } 
} 

E come chiamarlo:

DerivedClass B = new DerivedClass(); 
B.DoWork(); // This calls the new method. 

BaseClass A = (BaseClass)B; 
A.DoWork(); // This calls the old method. 
+0

Ciao, sto ricevendo errori in Visual Studio sulla linea –

21

Anche se questo suona irrazionale ma funziona

DerivedClass B = new DerivedClass(); 

BaseClass bc = JsonConvert.DeserializeObject<BaseClass>(JsonConvert.SerializeObject(B)); 
+2

La copia profonda è una delle soluzioni accettabili, ma ha un costo in termini di prestazioni. – Levitikon

+1

Dove inserisce le proprietà extra che possono essere nella classe derivata durante la serializzazione nella classe base? Per esempio. StudenteLa classe introdotta ha introdotto l'altezza dello studente mentre eredita da StudentBase. – Vaibhav

+1

@Vaibhav Ignora semplicemente tutte le proprietà extra :) –

2

Le soluzioni con new invece di override rottura del polimorfismo. Recentemente sono arrivato allo stesso problema e l'ho implementato nel modo seguente. La mia soluzione presenta i seguenti vantaggi:

  • virtual e override soggiorni in luogo;
  • nome BaseClass non viene utilizzato direttamente nel tipo colato, quindi se presento un intermedio MiddleClass nella gerarchia tra BaseClass e DerivedClass, che implementa anche DoSomething(); quindi l'implementazione di MiddleClass non verrà saltata.

Questa è l'implementazione:

public class BaseClass 
{ 
    public virtual void DoSomething() 
    { 
     Trace.Write("base class"); 
    } 
} 

public class DerivedClass : BaseClass 
{ 
    public override void DoSomething() 
    { 
     Trace.Write("derived class"); 
    } 

    public void BaseDoSomething() 
    { 
     base.DoSomething(); 
    } 
} 

L'utilizzo è:

DerivedClass dc = new DerivedClass(); 

    dc.DoSomething(); 

    dc.BaseDoSomething(); 
Problemi correlati