2013-06-26 16 views
5

Sto programmando un gioco di piccole dimensioni e ho due classi: Board e Piece. Board hanno (finora) uno Piece che può essere spostato nei bordi di Board.Il passaggio dell'oggetto (questo) al metodo di un campo è un approccio errato?

public class Board { 
    private Piece piece_; 
    private int width, height; 
    ... 

    movePieceDown() { 
    piece_.moveTo(this, 1, 2); 
    } 
} 

public class Piece { 
    public boolean moveTo(Board board, int x, int y) { 
    // move piece to new location (x,y) 
    // return true if successful 
    } 
} 

È brutto approccio se io in piece_.moveTo(this, 1, 2); riferimento passaggio al bordo in modo pezzo potrebbe passare alla nuova posizione se non ci sono ostacoli sul bordo? Senza passare il riferimento a Board, Piece non sa se ci sono ostacoli in una nuova posizione o è fuori dai confini del Board.

È a mio parere che ogni oggetto dovrebbe preoccuparsi solo di sé: Pezzo dovrebbe spostarsi in una nuova posizione e Board dovrebbe preoccuparsi se è legale o no, MA questo codice di esempio che ho pubblicato ha più senso e semplifica le cose.

TL; DR: Sto interrompendo alcune linee guida OOP con il passaggio dell'oggetto stesso al metodo di un campo o è un normale idioma OOP? Grazie in anticipo per chiarirmi questo.

+2

Perché stai passando un 'Board' per spostarePieceDown? –

+0

Sì, buona telefonata, mi dispiace, quello era un refuso quando stavo campionando il codice per la pubblicazione. Ora verrà modificato. – h00s

risposta

8

Non è un approccio negativo. Passare this a vari metodi non è cosa insolita in programmazione. Dipende solo dal tuo progetto e per quanto mi riguarda, nulla nella classe Piece.

Una cosa nella classe Board potrebbe confondere il metodo - movePieceDown. Hai parametro inutilizzabile Board board. Se avete intenzione di utilizzare this come argomento, rimuovere l'attributo perché il consiglio non dovrebbe ricevere altre schede come potenziali argomenti, e come un dato di fatto, non dovrebbe essere consapevoli che possono esistere altre schede.

Infine, è possibile verificare che Piece veda un'interfaccia dello Board come parametro di metodo e assicurarsi che tale contratto non cambierà mai. Ad esempio, potrebbe avere questi metodi:

public interface IBoard { 
    public boolean isFieldFree(int x, int y) 
    public Piece getPiece(int x, int y) 
} 

Non importa come si cambia l'attuazione del Consiglio più tardi, questo è qualcosa che dovrebbe sempre lavorare in modo da non dover rielaborare il codice Piece quando si cambia il Board . In questo modo è possibile applicare una regola che a Piece non può modificare lo stato della scheda (nell'interfaccia, non esporre metodi che modificano lo stato della scheda).

+0

Grazie per la tua risposta darijan e saluti dalla Croazia :). Sì, quello era un refuso nel mio codice di esempio, non doveva essere lì, buona chiamata. – h00s

+0

Felice di essere di aiuto. Nema na cemu.:) – darijan

2

Penso che sia una buona strategia, soprattutto quando è necessario passare un gruppo di variabili locali a un metodo. Invece di passare tutti quei locali, basta passare l'istanza dell'oggetto per mettere in ordine le firme dei metodi.

Basta essere sicuri di praticare una buona incapsulamento in modo che i metodi che ricevono questo parametro non modificano campi o chiamare metodi destinati ad avere accesso limitato.

3

Prima di tutto, perché la variabile del tuo pezzo termina con un trattino basso? Questo è solo strano: p

E per quanto riguarda la tua domanda. Gestirei tutte le cose legate ai pezzi come muoversi all'interno della classe pezzo. Se volete sapere su ciò che posizione sulla scacchiera sei, non avrei 2 variabili intere nel tuo pezzo di classe chiamati x e y.

Il pezzo non deve sapere se si scontrerà con qualche altro pezzo sulla scacchiera perché è qualcosa che la classe di bordo deve gestire quando si sposta un pezzo.

Quindi, ad esempio, se si sposta il pezzo su x = 1 e y = 2, è necessario verificare che ci sia già un pezzo in posizione 1,2 e rispondere di conseguenza.

Non c'è niente di sbagliato nel passare "questo" a un metodo di un'altra classe, ma da un punto di vista di programmazione orientato agli oggetti non è ottimale.

Solo i miei 2 centesimi :)

+0

Tutti i miei campi privati ​​terminano con underscore :) Rende facile distinguere le variabili di classe dalle variabili locali di scratch come indicato nelle linee guida Stile di programmazione Java - [link] (http://geosoft.no/development/javastyle.html) Grazie per i tuoi 2 centesimi :) – h00s

+0

@ h00s per usare caratteri di sottolineatura in questi casi è chiamato stile cattivo da Sun. So che l'oracolo ha preso il sopravvento, ma è arcaico e dovrebbe essere evitato se possibile. La tua altezza e larghezza sono anche private ma non finiscono con la sottolineatura tra l'altro :) – JREN

+0

uomo, non puoi davvero perderti nulla;) Underscores fa per me cose come costruttori 'Pezzo pubblico (Colore colore) {color_ = colore ; } 'Più chiaramente. Devo lasciarlo a favore di 'Piece pubblico (Colore colore) {this.color = color; } '? O, ancora meglio, ci sono più recenti linee guida Java che posso trovare? Grazie! – h00s

2

In generale, passando this non è raro, ma dipende dal caso. Se è Dio in questo caso dipende dai dettagli di implementazione. A Board ha diverse pipette che possono muoversi, quindi la posizione è la proprietà di un pezzo. Tuttavia, spostare un pezzo da una posizione all'altra potrebbe essere una funzione della scacchiera. Cosa succede, ad esempio, se la nuova posizione è già occupata? Il pezzo poi muoverà gli altri pezzi in giro? Questo sarebbe appropriato per il tuo design?

Dalla tua firma sul pezzo, mi aspetto che la funzione moveTo accetti una scheda, il che indica che un pezzo può spostarsi da una scheda all'altra. Durante la lettura del codice questo potrebbe essere fuorviante, a meno che non sia proprio così.

1

Non sono sicuro che si stia frenando qualsiasi regola di programmazione orientata agli oggetti, ma sembra certamente strano, dal momento che si sta chiamando un metodo su uno Board e quindi l'unica cosa che fa questo metodo è chiamare un metodo su Piece passando se stesso come parametro.

La programmazione orientata agli oggetti consiste nel vedere le cose come se fossero oggetti nel mondo reale. Seguendo questo approccio, lo guarderei come se il pezzo fosse sulla scacchiera, e per esempio la sua posizione è determinata dalla scacchiera, non da sola. Da questo approccio, quindi, spostare il pezzo è qualcosa fatto sulla lavagna, non il pezzo stesso.

Quindi, anche se non è corretto far passare this come parametro, avrei preferito definire il metodo:

public class Board 
{ 
    private Piece p; 
    // ... 

    public boolean movePieceDown() 
    { 
     // Move the piece to a new location using it's setters 
    } 
} 

Con questo approccio, oltre, dal momento che l'oggetto Board è a conoscenza di esso è attributi, poi la il codice risultante sarà molto più leggibile, perché non dovrai chiamare così tanti getter e setter (per controllare i limiti per esempio).

1

Per rispondere solo alla domanda specifica nel titolo (e non a opinioni generali sul design OO): No, non è una cattiva pratica, ma piuttosto comune.

Tuttavia, si tenga presente che passare il this all'esterno del mondo in un costruttore non è consigliato, poiché può portare a cattivi bug in uno scenario concorrente, in cui il ricevente potrebbe vedere la fonte in uno stato incoerente.

0

questo è passato implicitamente con una normale chiamata di metodo. Leggi questo answer che ho trovato sul forum.

Per questo è anche possibile leggere il JVM specification.

Problemi correlati