Domanda

Supponiamo che io abbia una classe "Applicazione". Per essere inizializzato sono necessarie alcune impostazioni nel costruttore. Supponiamo anche che il numero di impostazioni sia così elevato che è interessante metterle in una classe a parte.

Confronta le seguenti due implementazioni di questo scenario.

Implementazione 1:

class Application 
{
   Application(ApplicationSettings settings) 
   {
       //Do initialisation here
   }
}

class ApplicationSettings 
{
   //Settings related methods and properties here
}

Implementazione 2:

class Application 
{
   Application(Application.Settings settings) 
   {
       //Do initialisation here
   }

   class Settings 
   {
      //Settings related methods and properties here
   }
}

Per me, il secondo approccio è decisamente preferibile. È più leggibile perché enfatizza fortemente la relazione tra le due classi. Quando scrivo codice per creare un'istanza della classe Application ovunque, il secondo approccio sembrerà più bello.

Ora immagina solo che la stessa classe Settings a sua volta abbia avuto in qualche modo simili "relative" a sua volta e anche quella classe. Passa solo tre di questi livelli e il nome della classe sfugge di mano nel caso "non nidificato". Se annidi, le cose rimangono comunque eleganti.

Nonostante quanto sopra, ho letto persone che dicono su StackOverflow che le classi nidificate sono giustificate solo se non sono visibili al mondo esterno; cioè se vengono utilizzati solo per l'implementazione interna della classe contenitore. L'obiezione comunemente citata sta gonfiando le dimensioni del contenere il file sorgente della classe, ma le classi parziali sono la soluzione perfetta per quel problema.

La mia domanda è: perché siamo diffidenti nei confronti di " esposto pubblicamente " uso di classi nidificate? Ci sono altri argomenti contro tale uso?

È stato utile?

Soluzione

Penso che vada bene. Questo è fondamentalmente il modello del builder e l'utilizzo di classi nidificate funziona piuttosto bene. Inoltre, consente al costruttore di accedere ai membri privati ??della classe esterna, il che può essere molto utile. Ad esempio, puoi avere un metodo Build sul builder che chiama un costruttore privato sulla classe esterna che accetta un'istanza del builder:

public class Outer
{
    private Outer(Builder builder)
    {
        // Copy stuff
    }

    public class Builder
    {
        public Outer Build()
        {
            return new Outer(this);
        }
    }
}

Ciò garantisce che il unico modo di costruire un'istanza della classe esterna sia tramite il builder.

Uso un modello molto simile a questo nella mia porta C # dei protocol buffer.

Altri suggerimenti

Puoi usare gli spazi dei nomi per mettere in relazione cose che sono ... correlate.

Ad esempio:

namespace Diner
{
    public class Sandwich
    {
        public Sandwich(Filling filling) { }
    }

    public class Filling { }
}

Il vantaggio di questo rispetto all'uso delle classi come se fossero spazi dei nomi è che puoi facoltativamente usare usando sul lato chiamante per abbreviare le cose:

using Diner;

...

var sandwich = new Sandwich(new Filling());

Se usi la classe Sandwich come se fosse uno spazio dei nomi per Filling , devi usare il nome completo Sandwich.Filling per fare riferimento a Riempimento .

E come dormirai la notte sapendolo?

Potresti voler controllare cosa Microsoft deve dì sull'argomento. Fondamentalmente è una questione di stile, direi.

Un altro esempio pratico che ho per un uso valido delle classi nidificate pubbliche è nel modello MVC quando uso un modello con una proprietà IEnumerable. ad esempio:

public class OrderViewModel
{
public int OrderId{ get; set; }
public IEnumerable<Product> Products{ get; set; }

public class Product {
public string ProductName{ get; set; }
public decimal ProductPrice{ get; set; }
}

}

Lo uso perché non voglio che la classe Product venga riutilizzata all'esterno perché è personalizzata solo per quel modello di vista specifico che lo contiene. Ma non posso renderlo privato perché la proprietà Products è pubblica.

Uso principalmente le classi nidificate per perfezionare l'accesso alla classe nidificata e / o container.

Una cosa da ricordare è che una definizione di classe nidificata è fondamentalmente un membro di classe e avrà accesso a tutte le variabili private del contenitore.

Puoi anche usarlo per controllare l'utilizzo di una classe specifica.

Esempio:

public abstract class Outer
{
  protected class Inner
  {
  }
}

Ora, in questo caso, l'utente (della tua classe) può accedere alla classe Inner solo se implementa Outer.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top