Qual è il punto di getter e setter?

Possibile duplicato:
Perché usare getter e setter?

Ho letto libri su Java , dicendo che è bene creare setter e getter per variabili come y . Per esempio:

 public int getX(){ return x; } public void setX(int x){ this.x = x; } 

Ma qual è la differenza da questo e

 ...(shape.x)... // basically getX() 

e

 shape.x = 90; // basically setX() 

Se setter e getter sono migliori, potresti spiegarmi quali sarebbero i problemi pratici?

Molte ragioni:

  • Se si consente l’accesso al campo come

    shape.x = 90

quindi non è ansible aggiungere alcuna logica in futuro per convalidare i dati.

dì se x non può essere inferiore a 100 non puoi farlo, tuttavia se hai avuto setter come

 public void setShapeValue(int shapeValue){ if(shapeValue < 100){ //do something here like throw exception. } } 
  • Non è ansible aggiungere qualcosa come copia su logica di scrittura (vedere CopyOnWriteArrayList )
  • Un altro motivo è che per accedere ai campi al di fuori della tua class dovrai contrassegnarli come pubblici, protetti o predefiniti e quindi perdere il controllo. Quando i dati sono molto interni all'Incapsulazione della class e in generale alla metodologia OOPS .

Anche se per costanti come

 public final String SOMETHING = "SOMETHING"; 

consentirai l'accesso al campo in quanto non possono essere modificati, ad esempio variabile li posizionerai con getter, setter.

  • Un altro scenario è quando vuoi che la tua class sia immutabile, se permetti l'accesso al campo, allora stai infrangendo l'immutabilità della tua class poiché i valori possono essere cambiati. Ma se progettate attentamente la vostra class con getter e senza setter, mantenete intatta l'immutabilità.

Anche se in questi casi devi fare attenzione nel metodo getter per assicurarti di non dare riferimenti agli oggetti (nel caso in cui la tua class abbia oggetti come istanze).

Possiamo usare le variabili private in qualsiasi pacchetto usando getter e setter.

L’uso delle funzioni getter e setter consente vincoli e incapsulamento. Diciamo che x è il raggio. shape.x = -10 non avrebbe molto senso. Inoltre, se qualcuno tenta di impostare un valore non valido, puoi stampare un errore, impostare un valore predefinito o non fare nulla.

È buona prassi rendere private le variabili membro in modo che non possano essere modificate direttamente dai programmi che le utilizzano.

Funzioni del mutatore
incapsulamento

Un sacco di persone hanno menzionato l’incapsulamento delle specifiche dell’implementazione, che per me è la ragione principale per usare getter e setter in una class. Con questo, si ottengono anche molti altri vantaggi, compresa la possibilità di eliminare e sostituire l’implementazione per un capriccio senza dover toccare ogni parte di codice che utilizza la class. In un piccolo progetto, questo non è un grande vantaggio, ma se il tuo codice finisce come una libreria ben utilizzata (interna o pubblica), può essere un enorme vantaggio.

Un esempio specifico: numeri complessi in matematica . Alcune lingue li hanno come linguaggio o struttura, altri no. Userò una class mutevole come esempio qui, ma potrebbe altrettanto facilmente essere immutabile.

Un numero complesso può essere scritto sulla forma a + bi con parti reali e immaginarie, prestandosi bene a [gs]etRealPart e [gs]etImaginaryPart .

Tuttavia, in alcuni casi è più facile ragionare su numeri complessi su forma polare re^(iθ) , dando [gs]etRadius (r) e [gs]etAngle (θ).

Puoi anche esporre metodi come [gs]etComplexNumber(realPart, imaginaryPart) e [gs]etComplexNumber(radius, angle) . A seconda dei tipi di argomenti questi possono avere o meno bisogno di nomi diversi, ma in questo caso il consumatore della class può utilizzare o soddisfare le sue esigenze.

Le due forms sono intercambiabili; si può facilmente convertire da uno all’altro, quindi quale forma la class usa per l’archiviazione interna è irrilevante per i consumatori di quella class. Tuttavia, i consumatori possono utilizzare entrambe le forms. Se scegli la forma a + bi per la rappresentazione interna, e esponi che usando i campi piuttosto che getter e setter , non solo costringi i consumatori della class a usare quel modulo, non puoi neanche cambiare facilmente idea e sostituire la rappresentazione interna con re ^ (iθ) perché risulta essere più facile da implementare nel tuo particolare scenario. Sei bloccato con l’API pubblica che hai definito, che impone che in particolare le parti reali e immaginarie siano esposte utilizzando nomi di campi specifici.

Un altro buon motivo per l’utente getter e setter può essere compreso dal seguente esempio

 public class TestGetterSetter{ private String name ; public void setName(String name){ this.name = name ; } public String getName(String name){ return this.name ; } } 

Il punto di getter e setter è che solo loro sono destinati ad essere utilizzati per accedere al varialble privato, che stanno ottenendo o impostando. In questo modo fornisci l’incapsulamento e sarà molto più facile refactoring o modificare il tuo codice in seguito.

Immagina di usare il nome al posto del suo getter. Quindi, se si desidera aggiungere qualcosa di simile a un valore predefinito (ad esempio il nome predefinito è ‘Guest’ se non è stato impostato in precedenza), sarà necessario modificare sia la funzione getter che sayName.

 public class TestGetterSetter{ private String name ; public void setName(String name){ this.name = name ; } public String getName(String name){ if (this.name == null ){ setName("Guest"); } return this.name ; } } 

Non è necessario che getter e setter inizino con get e set – sono solo normali funzioni dei membri. Comunque è una convenzione per farlo. (specialmente se usi Java Beans)

Una delle migliori ragioni per cui posso pensare a getter e setter è la permanenza dell’API di una class. In linguaggi come python puoi accedere ai membri con il loro nome e convertirli in metodi in seguito. Poiché le funzioni si comportano in modo diverso rispetto ai membri di java quando si accede a una proprietà, questo è vero. Limitando il raggio d’azione in seguito si rompe il client.

Fornendo getter e setter un programmatore ha la possibilità di modificare liberamente membri e comportamenti purché aderiscano al contratto descritto dall’API pubblica.

Supponiamo, ipoteticamente, di trovare una libreria che faccia un lavoro migliore di quello che hai fatto nella tua class (YourClass). La cosa naturale da fare a questo punto è rendere YourClass un’interfaccia wrapper per quella libreria. Ha ancora un concetto di “X” che il codice cliente deve ottenere o impostare. Naturalmente, a questo punto è necessario scrivere le funzioni di accesso.

Se hai dimenticato di utilizzare le funzioni accessor e consenti al tuo codice client di accedere direttamente a YourClass.x, ora dovresti riscrivere tutto il tuo codice cliente che abbia mai toccato YourClass.x. Ma se stavi usando YourClass.getX () e YourClass.setX () dall’inizio, dovrai solo riscrivere YourClass.

Uno dei concetti chiave della programmazione, e in particolare della programmazione orientata agli oggetti, nasconde i dettagli di implementazione in modo che non vengano utilizzati direttamente dal codice in altre classi o moduli. In questo modo, se si modificano i dettagli di implementazione (come nell’esempio precedente), il codice client non conosce la differenza e non deve essere modificato. Per tutti i codici client, “x” potrebbe essere una variabile o potrebbe essere un valore calcolato al volo.

Questa è una semplificazione eccessiva e non copre tutti gli scenari in cui occultare l’implementazione è vantaggioso, ma è l’esempio più ovvio. Il concetto di hide i dettagli di implementazione è piuttosto fortemente legato a OOP ora, ma è ansible trovare discussioni su di esso risalenti a decenni prima che OOP venisse immaginato. Ritorna a uno dei concetti chiave dello sviluppo del software, che consiste nel prendere un grosso problema nebuloso e dividerlo in piccoli problemi ben definiti che possono essere risolti facilmente. Le funzioni accessorie aiutano a mantenere le tue piccole attività secondarie separate e ben definite: meno le tue lezioni conoscono l’interno dell’altro, meglio è.

Originariamente, il pattern getter / setter è stato creato per promuovere una buona progettazione orientata agli oggetti encapsulating gli interni di una class dalla sua interface esterna.

  • Nascondere la rappresentazione interna della proprietà

questa è la migliore risposta della tua domanda Perché usare getter e setter?

Ci sono molte ragioni. Qui ci sono solo alcune.

  1. Gli accessor, i getter in particolare, appaiono spesso nelle interfacce. Non è ansible stipulare una variabile membro in un’interfaccia.
  2. Una volta che esponi questa variabile membro, non puoi cambiare idea su come è implementata. Ad esempio, se vedi in seguito di passare a un modello come aggregazione, in cui vuoi che la proprietà “x” provenga effettivamente da qualche object nidificato, finisci per dover copiare quel valore e cercare di mantenerlo sincronizzato. Non bene.
  3. Il più delle volte si sta molto meglio non esponendo il setter. Non puoi farlo con campi pubblici come x.

Prima di entrare nella risposta, dobbiamo sapere qualcosa prima …! ” JavaBeans “.
JavaBeans sono classi java che hanno proprietà . Per il nostro scopo, pensiamo alle proprietà come variabili di istanze private. dal momento che sono private, l’unico modo in cui è ansible accedervi dall’esterno della class è attraverso i “metodi” della class.
I metodi che cambiano il valore di una proprietà sono chiamati metodi setter e i metodi che recuperano il valore di una proprietà sono chiamati metodi getter .

Direi che né i getter / setter né i membri pubblici hanno un buon design orientato agli oggetti. Entrambi interrompono l’incapsulamento OOP esponendo al mondo oggetti che probabilmente non dovrebbero accedere alle proprietà dell’object in primo luogo.

Questo viene fatto applicando il principio di incapsulamento di OOP.

Un meccanismo linguistico per limitare l’accesso ad alcuni dei componenti dell’object.

Ciò significa che è necessario definire la visibilità per gli attributi e i metodi delle classi. Ci sono 3 visibilità comuni:

  • Privato: solo la class può vedere e utilizzare gli attributi / metodi.
  • Protetto: solo la class e i suoi figli possono vedere e utilizzare gli attributi / metodi.
  • Pubblico: ogni class può vedere e utilizzare gli attributi / metodi.

Quando si dichiarano gli attributi privati ​​/ protetti, si consiglia di creare metodi per ottenere il valore (get) e modificare il valore (set). Un esempio di visibilità è la class [ArrayList][2] : ha una proprietà size per conoscere la dimensione effettiva dell’array interno. Solo la class deve cambiare il suo valore, quindi il codice è qualcosa di simile

 public class ArrayList { private int size; private Object[] array; public getSize() { return this.size; } public void add(E element) { //logic to add the element in the array... this.size++; } } 

In questo esempio, puoi vedere che il valore della dimensione può cambiare solo all’interno dei metodi della class, e puoi ottenere la dimensione effettiva chiamandola nel tuo codice (non mutandolo):

 public void someMethod() { List ls = new ArrayList(); //adding values ls.add("Hello"); ls.add("World"); for(int i = 0; i < ls.size(); i++) { System.out.println(ls.get(i)); } } 

Getter e setter racchiudono i campi di una class rendendoli accessibili solo attraverso i suoi metodi pubblici e mantenendo i valori stessi privati. Questo è considerato un buon principio OO.

Certo, spesso sembra un codice ridondante se non fa altro che impostare o restituire un valore. Tuttavia, i setter consentono anche di eseguire la convalida dell’input o la pulizia. Avere quello in un posto migliora l’integrità dei dati per i tuoi oggetti,

Perché stiamo usando un linguaggio di programmazione orientato agli oggetti. Qui stiamo usando il nascondiglio e l’incapsulamento dei dati. La variabile non dovrebbe essere accessibile direttamente dal mondo esterno (per aver nascosto i dati) quindi la creeremo in modo privato

shape.x

non è corretto. Il metodo Getter e setter è usato per ottenere e impostare il valore di x, che è il modo per ottenere l’incapsulamento.