Quando e perché utilizzare le classi annidate?

17

Usando la programmazione orientata agli oggetti abbiamo il potere di creare una classe all'interno di una classe (una classe nidificata), ma non ho mai creato una classe nidificata nei miei 4 anni di esperienza nella codifica.
A cosa servono le classi nidificate?

So che una classe può essere contrassegnata come privata se è nidificata e che possiamo accedere a tutti i membri privati di quella classe dalla classe contenente. Potremmo semplicemente mettere le variabili come private nella classe contenitore stessa.
Allora perché creare una classe annidata?

In quali scenari devono essere usate le classi annidate o sono più potenti in termini di utilizzo rispetto ad altre tecniche?

    
posta mayur rathi 28.03.2016 - 09:39
fonte

2 risposte

11

La caratteristica principale delle classi nidificate è che possono accedere ai membri privati della classe esterna pur avendo la piena potenza di una classe stessa. Inoltre possono essere private, il che consente di incapsulare in modo piuttosto potente in determinate circostanze:

Qui blocchiamo completamente il setter alla fabbrica poiché la classe è privata, nessun consumatore può abbatterlo e accedere al setter e possiamo controllare completamente ciò che è permesso.

public interface IFoo 
{
    int Foo{get;}      
}
public class Factory
{
    private class MyFoo : IFoo
    {
        public int Foo{get;set;}
    }
    public IFoo CreateFoo(int value) => new MyFoo{Foo = value};
}

Oltre a ciò è utile per l'implementazione di interfacce di terze parti in un ambiente controllato in cui possiamo ancora accedere ai membri privati.

Se per esempio fornissimo un'istanza di qualche interfaccia ad un altro oggetto, ma non vogliamo che la nostra classe principale la implementasse, potremmo farla implementare da una classe interna.

public class Outer
{
    private int _example;
    private class Inner : ISomeInterface
    {
        Outer _outer;
        public Inner(Outer outer){_outer = outer;}
        public int DoStuff() => _outer._example;
    }
    public void DoStuff(){_someDependency.DoBar(new Inner(this)); }
}
    
risposta data 28.03.2016 - 10:12
fonte
17

Tipicamente, una classe nidificata N viene creata all'interno di una classe C ogni volta che C ha bisogno di usare qualcosa internamente che non dovrebbe mai essere (direttamente) usato al di fuori di C, e per qualsiasi ragione che qualcosa debba essere un nuovo tipo di oggetto piuttosto di un tipo esistente.

Credo che questo spesso avvenga implementando un metodo che restituisce un oggetto che implementa un'interfaccia, e vogliamo mantenere il tipo concreto di quell'oggetto nascosto perché non sarà utile da nessun'altra parte.

L'implementazione di IEnumerable è un buon esempio di questo:

class BlobOfBusinessData: IEnumerable<BusinessDatum>
{
    public IEnumerator<BusinessDatum> GetEnumerator()
    {
         return new BusinessDatumEnumerator(...);
    }

    class BusinessDatumEnumerator: IEnumerator<BusinessDatum>
    {
        ...
    }
}

Semplicemente non c'è motivo per nessuno al di fuori di BlobOfBusinessData di conoscere o preoccuparsi del concreto tipo BusinessDatumEnumerator , quindi dovremmo tenerlo dentro BlobOfBusinessData .

Questo non voleva essere un esempio di "best-practice" su come implementare correttamente IEnumerable , solo il minimo indispensabile per ottenere l'idea, quindi ho omesso cose come un metodo IEnumerable.GetEnumerator() esplicito .

    
risposta data 28.03.2016 - 09:53
fonte

Leggi altre domande sui tag