Perché incapsulare le variabili contenitore? [duplicare]

0

Non ero sicuro di come formulare il titolo, ma c'è qualcosa che per me ha poco senso in OOP

Comprendo l'idea di incapsulamento, ovvero creare uno strato di protezione e astrazione, in modo che non ci sia accesso diretto a una determinata variabile.

Tuttavia, ci sono casi in cui l'incapsulamento non ha senso per me, permettimi di dimostrare di usare una semplice classe C #:

public class Person
{
    public int Age { get; private set; } // makes sense, the setter is isolated
    public string Name { get; private set; } // same story
    public string ZipCode { get; set; } // doesn't make sense
    public string Country { get; set; } // doesn't make sense either

    public string City // also makes sense
    {
        get { /*some logic that gets the city based on zip code and country */ }
        private set;
    }
}

Il mio problema qui è che, secondo le buone pratiche OOP, le variabili senza regole speciali, devono anche avere accessor e mutatori separati, ma perché dovrebbero se tutto ciò che fai è impostato e ottenere dati da e verso di essi?

Nel caso di Age e Name ha senso incapsularlo, perché il setter è privato, non puoi mutarlo fuori dall'ambito della classe, allo stesso modo con il campo City , che ha un getter speciale, che ottiene i dati in base a regole speciali.

Che differenza fa se avvolgo ZipCode e Country in una proprietà o no? Posso accedere completamente e mutare le variabili in entrambi i casi.

Qualcuno potrebbe chiarirlo?

    
posta Electric Coffee 21.05.2014 - 13:08
fonte

4 risposte

4

Hai ragione - non ha senso usare le proprietà quando i campi lo faranno (F # usa tecniche simili con Records, e potresti usare allo stesso modo Structs in C #). Se sei preoccupato per le prestazioni di runtime, tuttavia, non sarà mai un problema (l'impatto sulle prestazioni è trascurabile rispetto ad altri colli di bottiglia in qualsiasi sistema).

Come altri hanno già detto, l'incapsulamento riguarda la flessibilità e la manutenzione future del software. Più dipendenze hai nella tua classe, più è probabile che cambierà ad un certo punto. Quando cambia, potrebbe rompere molte delle dipendenze che lo usano.

In generale, tuttavia, il motivo dell'incapsulamento è quello di nascondere la tua implementazione. Ad esempio, potresti scoprire dopo aver scritto il tuo codice iniziale che ha più senso memorizzare i tuoi dati in un dizionario (so che normalmente non te lo aspetti, ma una cosa simile accade in WPF e in altri framework, quindi potrebbe solo) . Se hai fornito Proprietà invece dei campi, è facile cambiare quell'implementazione senza rompere nessuna delle tue dipendenze. Di fronte, sei libero di cambiare qualsiasi cosa nella tua classe senza doversi preoccupare delle dipendenze su di esso.

Se utilizzi Visual Studio, in genere è consigliabile utilizzare solo le proprietà, poiché i frammenti di codice "prop" e "propg" eseguono tutte le operazioni di digitazione per te.

    
risposta data 21.05.2014 - 13:48
fonte
5

Spesso accade che le variabili senza regole speciali finiscano con regole speciali. Se ciò accade, non desideri riscrivere il codice un'altra volta per utilizzare setter e getter, puoi farlo all'inizio e se vengono modificate delle regole puoi semplicemente cambiare l'implementazione del setter / getter.

Detto questo, so che in molti casi non sono stati necessari getters / setter, ovvero classi di vector3 / 4 nello sviluppo del gioco, spesso non hanno setter / getter, non hanno regole e non avranno mai per quanto rappresentano il vettore matematico.

Per quanto riguarda qualsiasi hit di perfomance, è comunque trascurabile nella maggior parte delle applicazioni, a meno che non si stia eseguendo un'applicazione estremamente critica come un gioco o una simulazione. Detto ciò; linguaggi come C ++ tendono a incorporare banalmente queste funzioni, eliminando qualsiasi overhead di chiamata di funzione.

    
risposta data 21.05.2014 - 13:16
fonte
2

(Gli esempi di codice sono in Java poiché non conosco C #).

Un altro punto che vorrei menzionare, è che a volte l'implementazione di come si memorizzano i dati cambia. E quando ciò accade, non vuoi che il codice client si rompa.

Ad esempio, è possibile memorizzare i dati in un array. Senza incapsulamento, il codice che ha bisogno di questi dati dovrebbe accedere direttamente alla matrice. Ad esempio, class.array[8] .

Ma cosa succede se si desidera modificare il modo in cui i dati vengono archiviati, ad esempio in ArrayList ? Tutto il codice cliente si rompe.

Con l'incapsulamento, dovresti creare un getter in primo luogo:

public int getValue(int i){
    return array[i];
}

Qualsiasi classe che ha bisogno di ottenere dati lo farebbe: class.getValue(8) .

E quando la struttura dei dati cambia da una matrice a una ArrayList , hai solo cambiato il getter, senza rompere tutto il codice client:

public int getValue(int i){
    return list.get(i);
}

Tutto il codice cliente rimane lo stesso: class.getValue(8) .

Questo è un esempio di come l'incapsulamento ti dà la flessibilità di cambiare l'implementazione interna di una classe senza preoccuparti che possa incidere e rompere altre cose.

    
risposta data 21.05.2014 - 13:49
fonte
0

Il vantaggio principale di poter modificare l'implementazione senza influire sui dipendenti è già stato indicato nelle altre risposte, ma vorrei sottolineare un altro vantaggio: l'uniformità. C'è un valore nell'avere accesso a tutti i tuoi "data slot" allo stesso modo.

Anche se sembra che i campi pubblici e le proprietà in C # siano accessibili allo stesso modo ( objectReference.FieldOrProperty ), è diverso nella riflessione. Per ottenere i campi pubblici usi Type.GetFields () e ottieni le proprietà che usi < a href="http://msdn.microsoft.com/en-us/library/vstudio/aky14axb"> Type.GetProperties () .

L'utilizzo di entrambi i tipi come slot di dati pubblici costringerà il codice di riflessione a gestirli entrambi, il che lo renderà più complesso. Pertanto, molte librerie che devono mappare slot di dati (ad esempio ORM, serializzatori) scelgono di gestire solo le proprietà, che sono più flessibili.

    
risposta data 21.05.2014 - 15:08
fonte

Leggi altre domande sui tag