2012-09-03 8 views
29

Non sono veramente sicuro di cosa sembra meglio o quando uso veramente in classi e proprietà astratte, o quando utilizzare proprietà non astratte. Proverò a fare un semplice esempio. Diciamo che ho questo:Non so quando utilizzare una proprietà astratta e quando non è

abstract class Human 
{ 
    public GenderType Gender { get; set; } 
    public string Name { get; set; } 
    public Date Born { get; set; } 
    public bool IsNerd { get; set; } 

    abstract public void Speak(); 
    abstract public void Sleep(); 
    abstract public void AnoyingPeopleOnStackOverflow(); 
    //... so on 
} 

class Peter : Human 
{ 
    //Peter is special, he got a second name 
    //But thats all, everything else is the same as like on other humans 
    public string SecondName { get; set; } 

    //...override abstract stuff 
} 

Va bene? Come ho capito, non devo usare una proprietà astratta se non voglio sovrascriverlo. E in questa situazione sarebbe ok, solo i metodi come Speak, Sleep e così via dovrebbero essere astratti.

Ora, se questo è ok, quando dovrei o dovrei usare una proprietà astratta?

+1

"Quando dovrei o dovrei usare una proprietà astratta" --- quando vuoi affermare che la classe figlio deve fornire un'implementazione specifica del metodo – zerkms

+1

1) Se questo fosse Java, probabilmente non ci sarebbero problemi. Probabilmente useresti solo una "interfaccia". Questo è essenzialmente quello che stai facendo qui in C#, non è vero?2) Il mio sentimento personale è che se ha bisogno di essere parte del "contratto", allora è appropriato dichiararlo nella tua classe astratta. In altre parole, penso che quello che hai fatto sia perfettamente OK. IMHO ... – paulsm4

+1

@ paulsm4 puoi farlo anche con C#. –

risposta

56

Utilizzare una proprietà astratta quando non si dispone di un'implementazione predefinita e quando le classi derivate devono implementarla.

Utilizzare una proprietà virtuale quando si ha un'implementazione nella classe base ma si desidera consentire l'override.

Utilizzare la parola chiave override per sovrascrivere un membro. Contrassegnare il membro come sealed override se non dovrebbe essere nuovamente sostituito.

Non contrassegnare la proprietà come abstract o virtual se non si desidera sovrascriverlo.

Utilizzare la parola chiave new per nascondere un membro non astratto, non virtuale (raramente è una buona idea).

How to: Define Abstract Properties

Trovo che le proprietà astratte si verificano spesso in un design che implica che essi avranno logica specifica-tipo e/o gli effetti collaterali. In pratica, stai dicendo "qui c'è un punto dati che tutte le sottoclassi devono avere, ma non so come implementarlo". Tuttavia,, le proprietà che contengono una grande quantità di logica e/o causare effetti collaterali potrebbero non essere desiderabili. Questa è una considerazione importante, anche se non esiste un modo giusto o sbagliato per farlo.

Vedi:

Personalmente, trovo che uso metodi astratti di frequente, ma raramente proprietà astratte.

4

Utilizzare l'abstract quando tutte le sottoclassi hanno per implementare il metodo/la proprietà. Se non è necessario per ogni sottoclasse implementarlo, non usarlo.

Come per l'esempio, se non è richiesto SecondName per ogni persona, non è necessario creare una proprietà astratta nella classe base. Se d'altra parte, ogni persona ha bisogno di un secondo nome, quindi rendila una proprietà astratta.

Esempio di uso corretto di una proprietà astratta:

public class Car 
{ 
    public abstract string Manufacturer { get; } 
} 

public class Odyssey : Car 
{ 
    public override string Manufacturer 
    { 
     get 
     { 
      return "Honda"; 
     } 
    } 
} 

public class Camry : Car 
{ 
    public override string Manufacturer 
    { 
     get 
     { 
      return "Toyota"; 
     } 
    } 
} 

Fare Maker astratto è corretto perché ogni macchina ha un costruttore e deve essere in grado di dire all'utente che che maker è.

1

Una proprietà astratta dovrebbe essere utilizzata dove si desidera che la classe esponga sempre la proprietà, ma dove non è possibile definire l'implementazione di tale proprietà, lasciandola fino alla forzatura della classe ereditaria.

C'è un esempio here, in cui la classe astratta è denominata Shape e espone una proprietà astratta Area. Non è possibile implementare la proprietà Area nella classe base, poiché la formula per l'area cambierà per ciascun tipo di forma. Tutte le forme hanno un'area (di qualche tipo), quindi tutte le forme dovrebbero esporre la proprietà.

L'implementazione in sé sembra giusta. Stavo cercando di pensare a un ragionevole esempio di una proprietà astratta per un Human, ma non riuscivo a pensare a qualcosa di ragionevole.

11

I membri astratti sono semplicemente membri virtuali che devono essere sostituiti. Lo usi per qualcosa che deve essere implementato, ma non può essere implementato nella classe base.

Se si desidera creare una proprietà virtuale e si desidera che sia sovrascritta nella classe che eredita la classe, la si renderebbe una proprietà astratta.

Se per esempio avete una classe di animali, la sua capacità di respirare, non sarebbe possibile detemine solo dalle informazioni che si tratta di un animale, ma è qualcosa che è abbastanza cruciale:

public abstract class Animal { 

    public abstract bool CanBreathe { get; } 

} 

Per un pesce e un cane l'implementazione sarebbe diversa:

public class Dog : Animal { 

    public override bool CanBreathe { get { return !IsUnderWater; } } 

} 

public class Fish : Animal { 

    public override bool CanBreathe { get { return IsUnderWater; } } 

} 
26

So cosa voglio che facciano, non mi interessa come lo fanno: interfaccia.

So cosa voglio che facciano, non mi importa come facciano alcuni di essi, ma ho idee ferme su come faranno (o almeno la maggior parte di loro) altri bit: classe astratta .

So cosa voglio che facciano, e come la maggior parte di loro lo farà: lezione di cemento con membri virtuali.

È possibile avere altri casi come ad es. una classe astratta senza membri astratti (non si può avere un'istanza di uno, ma quale funzionalità offre, offre completamente), ma sono più rari e normalmente si verificano perché una particolare gerarchia si offre in modo pulito e sfacciato a un dato problema.

(Per inciso, non penserei a un Peter come a un tipo di Umano, ma a ciascun peter come a un caso di umano che si chiama Peter. Non è giusto prendere in considerazione il codice di esempio in questo modo, ma quando stai pensando a questo tipo di problema è più pertinente del solito).

+3

+1 - Accetto, 'Peter' dovrebbe essere un'istanza di una sottoclasse di' Human', ad es. 'HumansWithTwoNames' –

+2

@TimMedora Sì, e tutti noi pensiamo ai nomi cattivi quando facciamo il codice di esempio, e normalmente non importa, ma questa è una domanda dove conta più della maggior parte. –

Problemi correlati