Proprietà astratta nella classe base Per forzare il programmatore a definirlo

7

Sto codificando con uno schema di stato per un dispositivo incorporato. Ho una classe base / astratta chiamata Stato e ogni classe di stato discreta (concreta) implementa la classe di stato astratta.

Nella classe di stato ho diversi metodi astratti. Se non implemento i metodi astratti nella classe discreta (concreta), Visual Studio darà un errore simile a questo:

...Error 1 'myConcreteState' does not implement inherited abstract member 'myAbstractState'

Ora: sto provando a creare una proprietà String per ogni stato chiamato StateName. Ogni volta che creo una nuova classe concreta, ho bisogno di definire StateName. Voglio VS per lanciare un errore se non lo uso. C'è un modo semplice per farlo?

Ho provato questo nella classe abstract / base:

public abstract string StateName { get; set; }

Ma non ho bisogno di implementare i metodi Get e Set in ogni stato.

Domanda riveduta: In una situazione ideale, a ciascuna Classe di stato verrà richiesto di definire StateName ed essere ereditata dalla classe di base astratta.

StateName = "MyState1"; //or whatever the state's name is

Se manca quell'istruzione, Visual Studio genererà un errore come descritto sopra. È possibile e se sì, come?

    
posta GisMofx 06.06.2015 - 19:26
fonte

3 risposte

12

Suppongo che il modo "corretto" per farlo sia quello di avere un costruttore protetto sulla classe base che richiede il nome dello stato come parametro.

public abstract class State
{
    private readonly string _name;

    protected State(string name)
    {
        if(String.IsNullOrEmpty(name))
            throw new ArgumentException("Must not be empty", "name");

        _name = name;
    }

    public string Name { get { return _name; } }
}

Gli stati concreti forniscono quindi un costruttore pubblico che chiama implicitamente il costruttore della classe base con il nome appropriato.

public abstract class SomeState : State
{
    public SomeState() : base("The name of this state")
    {
        // ...
    }
}

Poiché la classe base non espone nessun altro costruttore (né protetto né pubblico) ogni classe ereditaria deve passare attraverso questo singolo costruttore e quindi deve definire un nome.

Tieni presente che non è necessario fornire il nome quando si crea un'istanza di uno stato concreta perché il suo costruttore si occupa di ciò:

var someState = new SomeState(); // No need to define the name here
var name = someState.Name; // returns "The name of this state"
    
risposta data 07.06.2015 - 13:49
fonte
3

A partire da C # 6 (I believe - C #: The New and Improved C # 6.0 ) sei in grado di creare solo proprietà getter. Quindi potresti dichiarare la tua classe base in questo modo -

public abstract class State
{
    public abstract string name { get; }

    // Your other functions....
}

E poi nella tua sottoclasse puoi implementare State come così -

public class SomeState : State
{
    public override string name { get { return "State_1"; } }
}

O ancora più ordinato usando l'operatore lambda -

public class SomeState : State
{
    public override string name => "State_1";
}

Entrambi restituirebbero sempre "State_1" ed essere immutabili.

    
risposta data 24.04.2018 - 15:14
fonte
2

I tuoi requisiti sono una contraddizione:

I'm trying to create a String property for each State called StateName.

vs.

But I don't need to implement all of that in each State.

Non esiste una funzione linguistica che ti consenta di forzare l'esistenza di un membro solo in alcune sottoclassi. Dopo tutto, il punto di usare una super classe è di fare affidamento sul fatto che tutte le sottoclassi avranno tutti i membri della super classe (e possibilmente di più). Se vuoi creare classi che agiscono come State ma non hanno un nome, quindi per definizione, dovrebbero (/ can) non essere sottoclassi di State .

Devi modificare i tuoi requisiti o utilizzare qualcosa di diverso dalla semplice ereditarietà.

Una possibile soluzione con il codice così com'è potrebbe essere rendere il metodo in State non astratto e restituire una stringa vuota.

    
risposta data 06.06.2015 - 19:56
fonte

Leggi altre domande sui tag