Domanda

Questa domanda ha già una risposta qui:

Attualmente sto lavorando su un semplice gioco in Java con diverse modalità.Ho esteso una classe Game principale per inserire la logica principale all'interno delle altre classi.Nonostante ciò, la classe principale del gioco è ancora piuttosto consistente.

Dopo aver dato una rapida occhiata al mio codice, la maggior parte era composta da Getter e Setter (60%) rispetto al resto che è veramente necessario per la logica del gioco.

Un paio di ricerche su Google hanno affermato che Getter e Setter sono malvagi, mentre altri hanno affermato che sono necessari per una buona pratica OO e ottimi programmi.

Quindi cosa dovrei fare?Quale dovrebbe essere?Dovrei cambiare i miei Getter e Setter per le mie variabili private o dovrei mantenerli?

È stato utile?

Soluzione

V'è anche il punto di vista che la maggior parte del tempo, utilizzando setter rompe ancora l'incapsulamento, consentendo di impostare valori che sono prive di significato. Come esempio molto evidente, se si dispone di un contatore punteggio sul gioco che sempre e solo va in su, invece di

// Game
private int score;
public void setScore(int score) { this.score = score; }
public int getScore() { return score; }
// Usage
game.setScore(game.getScore() + ENEMY_DESTROYED_SCORE);

dovrebbe essere

// Game
private int score;
public int getScore() { return score; }
public void addScore(int delta) { score += delta; }
// Usage
game.addScore(ENEMY_DESTROYED_SCORE);

Questo è forse un po 'un esempio facile. Quello che sto cercando di dire è che discutere getter / setter vs campi pubblici spesso oscura i problemi più grandi con gli oggetti manipolare lo stato interno di ogni altri in modo intimo e, quindi, di essere troppo strettamente accoppiati.

L'idea è di rendere i metodi che fanno direttamente le cose che vuoi fare. Un esempio potrebbe essere come impostare lo stato 'vivo' nemici. Si potrebbe essere tentati di avere un metodo di setAlive (booleano vivo). Invece si dovrebbe avere:

private boolean alive = true;
public boolean isAlive() { return alive; }
public void kill() { alive = false; }

La ragione di questo è che se si modifica l'applicazione che le cose non hanno più un valore booleano "vivo", ma piuttosto un valore di "punti ferita", è possibile cambiare la situazione intorno senza rompere il contratto dei due metodi che è scritto in precedenza:

private int hp; // Set in constructor.
public boolean isAlive() { return hp > 0; } // Same method signature.
public void kill() { hp = 0; } // Same method signature.
public void damage(int damage) { hp -= damage; }

Altri suggerimenti

  • Molto malvagio:campi pubblici.
  • Un po' malvagio:Getter e setter dove non sono richiesti.
  • Bene:Getter e setter solo dove sono realmente richiesti: fai in modo che il tipo esponga un comportamento "più ampio" che accade utilizzo il suo stato, invece di trattare il tipo semplicemente come un deposito di stati che può essere manipolato da altri tipi.

Dipende davvero dalla situazione, a volte sì Fare voglio solo uno stupido oggetto dati.

Hai già avuto un sacco di buone risposte su questo, quindi mi limiterò a dare i miei due centesimi. Getter e setter sono molto, molto male. Essi consentono in sostanza si fa finta di nascondere interni del vostro oggetto quando la maggior parte del tempo tutto quello che hai fatto è buttato in codice ridondante che non fa nulla per nascondere stato interno. Per un semplice POJO, non c'è alcun motivo per cui getName () e setName () non può essere sostituito con obj.name = "Tom".

Se la chiamata al metodo sostituisce semplicemente l'assegnazione, quindi tutto quello che hai guadagnato preferendo la chiamata al metodo è il codice gonfiare. Purtroppo, la lingua ha sancito l'uso di getter e setter nella specifica JavaBeans, quindi i programmatori Java sono costretti ad usarli, anche se così facendo ha alcun senso.

Per fortuna, Eclipse (e probabilmente altri IDE come pure) consente di generare automaticamente li. E per un progetto di divertimento, una volta ho costruito un codice-generatore per loro in XSLT. Ma se c'è una cosa che mi piacerebbe sbarazzarsi di in Java, la sua l'eccessiva dipendenza dai getter e setter.

getter e setter applicare il concetto di incapsulamento nella programmazione orientata agli oggetti.

Avendo gli stati del oggetti nascosti dal mondo esterno, l'oggetto è davvero responsabile di se stesso, e non può essere modificato in modi che non sono destinati. Gli unici modi l'oggetto può essere manipolato sono attraverso metodi pubblici a vista, come ad esempio getter e setter.

Ci sono alcuni vantaggi per avere getter e setter:

1. Consentire cambiamenti futuri senza modifiche al codice che utilizza la classe modificata.

Uno il grande vantaggio di utilizzare un getter e setter è che una volta che i metodi pubblici sono definiti e arriva un momento in cui l'implementazione sottostante deve essere cambiato (ad es trovare un difetto che deve essere fissato, mediante un algoritmo diverso per migliorare le prestazioni, ecc), avendo il getter e setter essere l'unico modo per manipolare l'oggetto, consentirà il codice di non rompere, e il lavoro esistente come previsto, anche dopo la modifica.

Per esempio, diciamo che c'è un metodo setValue che imposta la variabile privata value in un oggetto:

public void setValue(int value)
{
    this.value = value;
}

Ma poi, ci fu un nuovo requisito che aveva bisogno di tenere traccia del numero di volte in cui è stato cambiato value. Con il setter nel luogo, il cambiamento è abbastanza banale:

public void setValue(int value)
{
    this.value = value;
    count++;
}

Se il campo value fosse pubblico, non v'è alcun modo semplice per tornare più tardi e aggiungere un contatore che tiene traccia del numero di volte che il valore è stato modificato. Pertanto, dopo aver getter e setter sono un modo per "a prova di futuro" la classe per le modifiche che possono venire più tardi.

2. Applicando i mezzi con cui l'oggetto può essere manipolato.

Un altro modo getter e setter sono utili per fare rispettare le vie l'oggetto può essere manipolato, pertanto, l'oggetto è in controllo del proprio stato. Con variabili pubbliche di un oggetto a vista, può essere facilmente danneggiata.

Ad esempio, un oggetto ImmutableArray contiene un array int chiamato myArray. Se la matrice fosse un campo pubblico, semplicemente non sarà immutabile:

ImmutableArray a = new ImmutableArray();
int[] b = a.myArray;
b[0] = 10;      // Oops, the ImmutableArray a's contents have been changed.

Per implementare una gamma veramente immutabile, un getter per l'array (metodo getArray) dovrebbe essere scritto in modo che restituisce una copia della sua matrice:

public int[] getArray()
{
    return myArray.clone();
}

E anche se si verifica quanto segue:

ImmutableArray a = new ImmutableArray();
int[] b = a.getArray();
b[0] = 10;      // No problem, only the copy of the array is affected.

Il ImmutableArray è davvero immutabile. Esponendo le variabili di un oggetto consente di essere manipolato in modi che non sono destinati, ma solo esporre determinati modi (getter e setter), l'oggetto può essere manipolato in modi prefisso.

immagino aventi getter e setter sarebbero più importante per le classi che fanno parte di un'API che sta per essere utilizzato da altri, in quanto permette di mantenere l'API intatto e invariato pur consentendo modifiche nell'attuazione sottostante.

Con tutti i vantaggi di getter e setter ha detto, se il getter è semplicemente restituire il valore della variabile privata e il setter è semplicemente accettare un valore e di assegnarlo a una variabile privata, sembra che i getter e setter sono solo estranei e davvero uno spreco. Se la classe sta per essere solo per uso interno da un'applicazione che non sta per essere utilizzato da altri, utilizzando getter e setter ampiamente potrebbe non essere così importante come quando si scrive un'API pubblica.

Sono assolutamente sono il male.

@coobird purtroppo assolutamente non "rispettare il concetto di incapsulamento", tutto quello che fanno è rendere pensi di incapsulamento dei dati, quando in realtà si sta esponendo i dati tramite una proprietà con manie di grandezza metodo. Tutto ciò che un getter / setter fa un campo pubblico fa meglio.

In primo luogo, se si desidera che i dati pubblici, rendono pubblico, sbarazzarsi dei metodi getter e setter per ridurre il numero di metodi il cliente deve guadare attraverso e rendere più cognitivamente più semplice per il cliente di cambiare il suo valore per esempio.

object.field = value;

al posto del più cognitivamente intensa

object.setField(value);

in cui il cliente deve ora verificare il metodo getter / setter per vedere se ha effetti collaterali.

In secondo luogo, se si ha realmente bisogno di fare qualcosa di diverso nel metodo, perché chiamare un metodo get / set, quando è avuto più responsabilità che semplicemente ottenere o l'impostazione? O seguire la SRP o chiamare il metodo qualcosa che in realtà ti dice quello che il tutto metodo non come esempi di Zarkonnen ha accennato ad es.

public void kill(){
    isAlive = false;
    removeFromWorld(this);
}

anziché

public void setAlive(boolean isAlive){
    this.isAlive = isAlive;
    if (isAlive)
        addToWorld(this);
    else
        removeFromWorld(this);
}

da dove viene il metodo setAlive (booleano) dire al cliente che come effetto collaterale che sarà rimuovere l'oggetto dal mondo? Perché il cliente dovrebbe avere alcuna conoscenza del campo isAlive? Inoltre ciò che accade quando l'oggetto viene aggiunto nuovamente al mondo, dovrebbe essere re-inizializzato? Perché la cura del cliente nulla di tutto ciò?

IMHO La morale è a metodi di nome per dire esattamente quello che fanno, seguire la SRP e sbarazzarsi di getter / setter. Se c'è problemi senza getter / setter, dire a oggetti per fare il proprio lavoro sporco all'interno della propria classe invece di cercare di fare le cose con loro in altre classi.

Qui finisce il mio sproloquio, mi dispiace;)

E 'un pendio scivoloso.

Un oggetto semplice trasferimento (o di un oggetto Parameter) possono avere il solo scopo di contenere alcuni campi e fornendo i loro valori su richiesta. Tuttavia, anche in questo caso degenere si potrebbe sostenere che l'oggetto deve essere immutabili -. Configurato nel costruttore ed esponendo solo get ... metodi

C'è anche il caso di una classe che espone alcuni "manopole di controllo"; UI della vostra autoradio, probabilmente può essere inteso come esporre qualcosa di simile getVolume, setVolume, getChannel, e setChannel, ma il suo vero funzionalità riceve segnali ed emettendo il suono. Ma quelle manopole non espongono molti dettagli attuazione; non si sa da quelle caratteristiche di interfaccia se la radio è transistor, per lo più, al software o tubi a vuoto.

Quanto più si inizia a pensare a un oggetto come un partecipante attivo in un compito di problem-dominio, più si pensa in termini di chiedendo di fare qualcosa invece di chiedere per raccontare circa il suo stato interno, o chiedere per i propri dati in modo altro codice può fare qualcosa con quei valori.

Quindi ... "male"? Non proprio. Ma ogni volta che siete inclini a mettere in un valore ed esporre sia get ... e set ... metodi su tale valore, chiedetevi perché, e che cosa reponsibility di quell'oggetto è in realtà. Se l'unica risposta che si può dare voi stessi è: "Per mantenere questo valore per me", allora forse qualcosa oltre OO sta succedendo qui.

La classe di gioco è probabilmente seguendo il dio oggetto antipattern se espone che molte variabili. Non c'è niente di sbagliato con getter e setter (anche se la loro verbosità in Java può essere un po 'fastidioso); in un'applicazione ben progettata in cui ogni classe ha una funzionalità nettamente separato, non avrete bisogno di decine di loro in una sola classe.

Modifica Se il punto principale per i getter e setter è quello di "configure" la classe gioco (capisco il tuo commento in questo modo), allora il tuo probabilmente non hanno bisogno i getter (è perfettamente bene per una classe per accedere alle proprie variabili private senza usare metodi get), e probabilmente si può crollare molti dei setter in "setter di gruppo" che impostare diverse variabili che appartengono insieme concettualmente.

La presenza di getter e setter tende ad indicare (un "odore" se siete in quel genere di lingua scuola primaria) che c'è un problema di progettazione. getter e setter banali sono a mala pena distinguibili dai campi pubblici. In genere il codice che opera sui dati sarà in una classe diversa -. Poveri incapsulamento, e quello che ci si aspetta da programmatori non a suo agio con OO

In alcuni casi getter e setter vanno bene. Ma, come regola di tipo sia con getter e setter indica problemi di progettazione. Getters lavorano per immutabilità; setter lavorano per "dire non chiedere". Sia immutabilità e "dicono non chiedere" sono buone scelte di design, purché non siano applicate in uno stile di sovrapposizione.

La mia opinione è che i getter e setter sono un requisito per i buoni programmi. Bastone con loro, ma non scrivere inutili getter / setter -. Non è sempre necessario trattare direttamente con tutte le variabili

Non mi credo che siano il male. Ma mi piacerebbe vivere in un mondo in cui non ho mai dovuto usare loro a meno che non avevo proprio bisogno di.

Un esempio che ho letto sopra è stato future-proofing codice. Ad esempio:

public void setValue(int value)
{
    this.value = value;
}

Poi, le esigenze cambiano ed è necessario tenere traccia di quante volte il valore è stato impostato.

public void setValue(int value)
{
    this.value = value;
    count++;
}

Questa è bella. Capisco. Tuttavia, in Ruby, sarebbe il seguente non servire allo stesso scopo?

someobject.my_value = 100

In seguito, è necessario tenere traccia è stato impostato il numero di volte my_value. Ebbene, si potrebbe non solo ignorare il setter THEN e solo THEN

def my_value=(value)
    @my_value = value
    @count++
end

Sono tutti per codice bello, ma devo ammettere che, guardando attraverso le montagne di classi Java che abbiamo e vedere letteralmente migliaia e migliaia di righe di codice che non sono altro che di base getter / setter è brutto e fastidioso.

Quando stavo sviluppando in C # a tempo pieno, abbiamo utilizzato le proprietà pubbliche per tutto il tempo e ha fatto personalizzati getter / setter solo quando necessario. Ha lavorato come un fascino e non rompere nulla.

Come sempre l'unica risposta è: dipende. Se siete gli unici Peron toccare il codice, si può fare tutto quello che a tuo agio con, tra cui i collegamenti taking.

Uno dei vantaggi di utilizzare setter è che i controlli devono essere eseguiti in un solo punto nel codice.

Si potrebbe desiderare di prestare una certa attenzione più vicino a quello che viene effettivamente get e set da questi metodi. Se stai usando loro di fornire l'accesso a valori costanti si sono probabilmente meglio utilizzando costanti.

Questo dipende dal linguaggio di programmazione in questione. La tua domanda è inquadrata nel contesto di Java, dove sembra che getter e setter sono generalmente considerati come una cosa buona.

Al contrario, nel mondo di Python, che sono generalmente considerati come cattivo stile: aggiungono righe al codice senza in realtà l'aggiunta di funzionalità. Quando i programmatori Python devono, possono utilizzare metaprogrammazione per catturare ottenere e / o l'impostazione di attributi degli oggetti.

In Java (almeno la versione di Java Ho imparato un po 'di una decina di anni fa), che non era possibile. Così, in Java di solito è meglio usare getter e setter religiosamente, in modo che, se necessario, è possibile ignorare l'accesso alle variabili.

(Questo non rende Python necessariamente migliore di Java, solo diverso.)

Proprio A proposito: In aggiunta a tutte le ottime risposte in questa discussione, ricordate che di tutte le ragioni si può venire con favore o contro getter / setter, le prestazioni non è uno (come qualcuno potrebbe credere). La JVM è abbastanza intelligente per inline getter / setter banali (anche quelli non final, fintanto che non sono effettivamente sovrascritti).

Si consiglia di sostituire alcuni dei vostri corsi per classi di valore. Questo vi permetterà di rimuovere il getter ed evitare problemi quando il contenuto viene cambiato da sotto di te.

Se avete bisogno di accesso esterno ai singoli valori di campi, utilizzare getter e / o setter. In caso contrario, non lo fanno. Non utilizzare campi pubblici. E 'così semplice! (Ok, non è mai che semplice, ma è una buona regola).

In generale si dovrebbe anche trovare che è necessario fornire un setter molto meno spesso di un getter - soprattutto se si sta cercando di rendere i vostri oggetti immutabili - che è una buona cosa (ma non sempre la scelta migliore) - ma anche in caso contrario.

Sono stato di programmazione in java per qualche mese fa, e ho imparato che dovremmo usare getter e setter solo quando è necessario per l'applicazione

divertirsi:)

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