Creazione di varianti di una classe pesante di proprietà

2

Quale tipo di modello o disegno può impedire la creazione di una classe piena di proprietà che non sono sempre utilizzate?

Esempio

class Car{
   public string type;
   public string name;
   public DateTime manufactured;
   public int model;
   public Color color;
   public int VIN;
   // ..and on
}

public Car(string name, Color color){
    this.name = name;
    this.color = color;
}

A volte vuoi fare una macchina con solo alcune informazioni, come la marca e il modello, ma vuoi sempre avere alcune impostazioni predefinite. Come si evitano in questo caso 20 classi di bambini o sovraccarichi del costruttore?

    
posta user2410532 24.09.2015 - 04:16
fonte

5 risposte

2

Puoi evitare sovraccarichi di più costruttori usando un costruttore con argomenti facoltativi con nome.

public Car(string name, Color color, string type="sedan", string model = "Taurus")

... che puoi chiamare così:

var car = new Car("Ford", Color.Red)

type e model sono facoltativi; imposterà type su "sedan and model" su "Toro" automaticamente, a meno che non li sovrascrivi nell'elenco dei parametri.

Ulteriori letture
Argomenti nominativi e opzionali

    
risposta data 24.09.2015 - 05:17
fonte
2

Il modo per evitare di avere un sovraccarico di zillion nel costruttore è assegnare le proprietà (dovrebbero essere proprietà, BTW, non campi,) al di fuori del costruttore.

Sometimes you want to make a Car with just some info, like the make and model, but you always want it to have a few defaults.

Quindi fai esattamente questo: fai in modo che il costruttore richieda le informazioni richieste, quindi imposta il resto delle proprietà sui valori predefiniti. Quindi puoi chiamare il costruttore con la sintassi della proprietà aggiuntiva se desideri sovrascrivere quelle predefinite:

var myCar = new Car("Ford", "Taurus") {Color = ModelColors.Blue, VIN = myVIN};
    
risposta data 24.09.2015 - 17:24
fonte
2

Un'opzione spesso trascurata in questo caso sta separando l'interfaccia dall'implementazione. Certo, se puoi vivere con loro come proprietà pubbliche, con tutti i mezzi. Se questa non è un'opzione, considera di fare di Car una classe privata della classe che farebbe l'istanziazione e quindi di creare un'interfaccia per i getter in questo modo.

interface ICar
{
    int Foo{get;}
    string Bar{get;}
}

class SomeService
{
    private class MyCar : ICar
    {
        int Foo{get;set;}
        string Bar{get;set;}
    }
    public ICar MakeCar()
    {
        return new MyCar{/*todo*/}
    }
}

Ora il chiamante ha il controllo completo mentre continui a fornire incapsulamento ai consumatori.

    
risposta data 24.09.2015 - 09:08
fonte
0

Un'altra opzione è semplicemente renderle proprietà pubbliche. Dal momento che sono opzionali, il chiamante dovrebbe essere in grado di assegnare loro un valore o impostarli su null se hanno già un valore. Ciò renderebbe più semplice per i chiamanti assegnare i valori secondo necessità. A volte i chiamanti hanno determinati flussi di codice che consentono di assegnare le proprietà a quel punto in modo molto più conveniente. Senza renderli proprietà, non può essere supportato.

Se segui questo modello, potresti renderli proprietà automatiche e ciascun metodo può convalidare le proprietà richieste e generare eccezioni appropriate. Questo succede facendo molte convalide con diverse combinazioni nel costruttore (indipendentemente dal fatto che le prendiate come parametri opzionali nel costruttore o meno).

Come per i chiamanti, possono chiamare il costruttore con le proprietà richieste e utilizzare gli inizializzatori per assegnare valori alle proprietà automatiche, ad es.

public class Car
{
    public string Name { get; set; }
    public DateTime Manufactured { get; set; }
    public int Model { get; set; }
    public Color Color { get; set; }
    public int Vin { get; set; }
    public Car (string name, DateTime manufactured)
    { ... } // required properties

    public Register()
    {
        if (Vin == 0) { throw new SomeException(); }
        // Code to register here
    }
}

E che consuma codice:

public void Method()
{
    Car myCar = new Car("myCar", DateTime.Now())
    {
        Model = 5 // Every caller may not need to assign it.
    };

    if (someCondition) { myCar.Color = Color.Red; }
    MethodA(car);
    car.Register();
}

private void MethodA(Car car)
{
    if (someCheck || methodCall())
    { car.Vin = 888; }
}

Si noti che questo salva il secondo codice dal dover utilizzare altre variabili per restituire un valore da un metodo figlio, che può operare direttamente su auto e impostare la proprietà. Tenendo da parte la discussione sul design, in un codice più coinvolto, ho dovuto modificare le mie classi per supportare questo modello (ad esempio proprietà automatiche) anziché i controlli rigidi nei costruttori.

Ci possono essere alcune eccezioni a questo schema, ma questo sembra essere un pattern ampiamente utilizzato e puoi trovare molte librerie di classi .NET framework che supportano questo. Lo uso di default a meno che non ci sia un motivo per non farlo.

    
risposta data 24.09.2015 - 06:47
fonte
0

Analizza quali proprietà lavorano insieme e crea una classe di ciascuno di questi gruppi. Possono raggrupparsi attorno ai sistemi naturali come elettrico, motore, trasmissione; e gruppi nozionali come performance, identità, opzioni.

Mentre lavori questi gruppi cercano proprietà ridondanti. Queste singole proprietà potrebbero essere DRYed fino a diventare una classe che viene utilizzata per inizializzare minimamente qualsiasi auto. Altre classi di aspetto dell'auto avranno un riferimento a questo se necessario.

Dato un auto minimamente inizializzato, puoi caricare pigro gli altri aspetti della vettura, se necessario.

Mentre tutto quanto sopra sembra solo composizione, i requisiti completi e l'analisi del progetto produrranno complementari ereditarietà, composizione, sovraccarico del costruttore e modelli come fabbrica, costruttore o visitatore per consentire una costruzione flessibile e garantire l'integrità degli oggetti.

Il codice cliente non dovrebbe impostare le singole proprietà dell'oggetto-aspetto dell'automobile. Il cliente avrebbe bisogno di sapere tutto sulle funzionalità interne della classe dell'auto per farlo nel modo giusto. Quindi, oltre a un factory per l'inizializzazione, potresti avere classi builder che incapsulano / controllano l'iniezione di ulteriori oggetti aspetto auto, i parametri del costruttore che garantiscono che l'oggetto auto sia in uno stato valido.

Le classi e le fabbriche dei costruttori di cui sopra possono funzionare con classificazioni di veicoli di grandi dimensioni come auto sportive, camion, berline di lusso, auto volanti, ecc.

Infine, queste classi di aspetto dell'auto non dovrebbero essere solo stupide cose tipo DTO: tutte lo stato e nessuna funzione. Trovo che anche cose minime come l'override di ToString, Equals, forse implementino IComparable, rendano la composizione migliore ei livelli di composizione tendano a rimanere più semplici.

    
risposta data 25.09.2015 - 05:41
fonte

Leggi altre domande sui tag