2010-02-01 17 views
8

Data la definizione di classe riportata di seguito. Come procedere nel decidere se i metodi di stub dovrebbero essere statici o non statici?metodo statico o non statico per classe immutabile

class Point { 
    private final int x; 
    private final int y; 

    public Point(int x, int y) { 
     this.x = x; 
     this.y = y; 
    } 

    // Should the methods add(), subtract() and inverseOf() be non-static ... 

    public Point add(Point point) { 

    } 

    public Point subtract(Point point) { 

    } 

    public Point inverseOf() { 

    } 


    // Or static? 

    public static Point add(Point point1, Point point2) { 

    } 

    public static Point subtract(Point point1, Point point2) { 

    } 

    public static Point inverseOf(Point point) { 

    } 
} 
+1

È questo compito? –

+0

No, questo non è compito. Sto solo passando un momento difficile per capire se determinati metodi nella mia applicazione debbano essere statici o non statici. Ho usato un esempio banale per garantire che le specifiche della mia applicazione non distraggano gli elementi chiave della domanda, vale a dire statici o non statici. –

+0

Farei sicuramente quella classe 'final'. Inoltre è una buona idea rendere il costruttore 'private' e aggiungere un metodo di creazione statico. –

risposta

9

Vorrei andare per esempio i metodi. Si ha quindi la capacità di rendere i metodi parte di un inteface e sovrascriverli. Otterrai il vantaggio quando dovrai gestire punti 2D o punti 3D e disporre di un codice client che non gli interessa e che dovrà semplicemente eseguire operazioni sui punti che implementano l'interfaccia.

+0

Stavo semplicemente scrivendo la stessa risposta da solo. Sei più veloce, quindi +1 :-) – Mendelt

+3

Solo il motivo per avere metodi statici sarebbe se hai molte chiamate in cui un'istanza Punto Null è valida. – james

0

Utilizzare un metodo statico quando il corpo del metodo non dipende da una particolare istanza.

Come esempio, guarda il tuo metodo add(Point, Point). Si sommano i due Point s che vengono passati alla funzione come argomenti e si restituisce un altro Point. Questo ha davvero bisogno di un riferimento interno this ad alcuni Point?

D'altra parte, si dispone di un metodo add(Point). Presumibilmente questo aggiunge l'argomento della funzione all'istanza: in tal caso, dovresti renderlo un metodo di istanza in modo da avere entrambi i valori Point s.

Modifica: Penso di aver frainteso, in origine. Guardando indietro, hai le firme corrette per entrambe le implementazioni statiche e non statiche. A questo punto, direi che è una questione di stile, come sapete entrambi funzioneranno correttamente. Come vuoi che la tua point-class sia usata? Pensa se rende il codice più intuitivo per dire Point a = Point.add(b, c) o Point a = b.add(c). Personalmente, mi piace il primo, poiché mi dice che nessuno degli operandi verrà modificato.

+0

Per il downvoter: è generalmente buona norma lasciare un commento che spieghi il downvote. – danben

+0

In aumento, in particolare perché odio i downvoters che non spiegano perché pensano che tu abbia torto ... quindi sei lasciato ad assumere che è solo perché non sono d'accordo con la tua opinione (piuttosto che un problema fattuale). – RHSeeger

+0

@RHSeeger - anzi. Non c'è modo di sapere se si tratta di un reclamo legittimo o solo di uno SCORSO. – danben

0

È naturale che queste funzioni non siano statiche. Ma se dubiti di fare riferimento a GRASP, loro descrivono cose come questa.

Secondo l'esperto di informazioni GRASP queste funzioni non devono essere statiche.

Nonostante il fatto non ci sono informazioni dirette sul metodo statico, c'è

Information Expert ci porterà a luogo una responsabilità in classi con la maggior parte delle informazioni necessarie per compierla.

Se si rendono i metodi statici, si sposterà ulteriormente la logica dai dati effettivi e sarà necessario passare i dati al metodo.

La rimozione di statico avvicina la logica ai dati che utilizza.

+0

Non mi sembra che la pagina GRASP a cui si fa riferimento fornisca realmente alcuna indicazione sul fatto che i metodi debbano essere statici o meno, solo che dovrebbero essere metodi della classe in questione (che sono in entrambi i casi). – RHSeeger

+0

Perché devono essere metodi di istanza? Puoi citare qualche particolare motivo? – danben

+0

Il metodo statico non ha accesso ai dati di istanza. Secondo l'esperto di informazioni, è necessario posizionare i metodi per posizionare dove hanno accesso. Rimozione della logica di messa statica più vicina ai dati. –

-2

Nel tuo caso deve essere non statico a meno che non si cambi la firma in public static Point add(Point point1, Point point2).

MODIFICA: ho votato. Va bene. Non stavo cercando di dare un suggerimento banale come mettere il metodo statico davanti. In questo caso, un metodo di istanza è migliore, ma non c'è davvero una risposta singa. Dipende solo dalle tue preferenze.

+0

Penso che potresti non aver letto la domanda da vicino. – BobMcGee

0

Tendo a controcorrente, ma in entrambi i casi mi sembra ragionevole.

  • I metodi devono, ovviamente, essere parte del metodo Point, dal momento che si occupano specificamente di punti
  • Per i metodi che usano due punti, non c'è niente su di loro che implicano hanno bisogno di ulteriori informazioni su uno dei punti di l'altro...Quindi non c'è alcuna spinta su quale istanza il metodo sarebbe un membro non statico di.

Per un linguaggio come Java, andrei con metodi statici, in particolare a causa del secondo punto sopra. Per un linguaggio che ha un sovraccarico dell'operatore (come Ruby), andrei con un metodo di istanza per trarne vantaggio.

+0

Per il downgoter: è generalmente buona norma lasciare un commento che spieghi il downvote. – RHSeeger

2

Semantico, l'approccio statico sembra avere un po 'più senso. Ovviamente entrambi funzioneranno, ma l'approccio non statico dà la precedenza a un punto piuttosto che a un altro, e inoltre implica che il punto1 (il metodo con cui viene chiamato add) possa essere modificato come risultato della chiamata.

Come sviluppatore utilizzando le classi, se ho visto la seguente:

Point p1 = new Point(1,2); 
Point p2 = new Point(2,3); 

p1.Add(p2); 

o ..

Point p1 = new Point(1,2); 
Point p2 = new Point(2,3); 

Point.Add(p1, p2); 

mia inclinazione naturale sarebbe quello di ritenere che il metodo add() nel settore non -la versione statica modifica il punto1 per aggiungere il risultato del punto 2. Con l'approccio statico, è più chiaro (anche se non garantito!) che il metodo è puro e che i punti rappresentativi non vengono modificati.

+0

Passare con metodi non statici ma cambiare i nomi in più e in meno potrebbe essere una buona via di mezzo –

3

Penso che dipenda da cosa stai cercando di realizzare. Se stai fornendo un metodo che aggiunge due punti insieme, allora vuoi un metodo statico. Ma se vuoi un metodo che aggiunge un punto ad una determinata istanza di Point, allora vuoi un metodo non statico.

Se si utilizzano metodi statici, è possibile considerare di inserire i metodi statici in una classe di utilità separata (PointCalculator) che contiene solo metodi statici. Questo è simile alla classe Math.

+0

Dato che la classe è immutabile, non capisco quale sia la differenza tra "fornire un metodo che aggiunge due punti" e "un metodo che aggiunge un punto a una determinata istanza Punto" –

+0

Un metodo statico veicola che si sta aggiungendo due punti per creare un nuovo punto. Un metodo non statico comunica che si sta modificando il punto esistente. Il che non è vero, ovviamente, perché stai restituendo un nuovo Punto. Ad esempio un utente può scrivere p1.add (p2); (l'utente potrebbe pensare di aver aggiunto a p2 a p1 e il nuovo valore è in p1) anziché Point p3 = p1.add (p2) ma Punto p3 = Punto.add (p1, p2) è molto chiaro. Quindi questo è un punto per statico. – richs

3

Preferisco i metodi non statici più orientati agli oggetti (sì, l'utilizzo di troppi metodi statici interrompe il beneficio di oggetti come il polimorfismo, l'ereditarietà ...), anche se il tuo Point è immutabile. In realtà, ciò sarebbe coerente con il modo in cui sono state progettate classi come BigDecimal o BigInteger. Oltre a questo, static methods make classes harder to test, quindi preferisco evitare di usarli, se possibile, soprattutto quando ha senso.

-1

Questi metodi devono essere statici perché la classe stessa si presta a essere creata tramite il costruttore e i valori assegnati una volta a causa di xey finale. Ciò significa che puoi creare Punti, ma non manipolare i loro dati andando avanti. I metodi Add/Substract/Etc sono metodi di utilità che non dovrebbero richiedere l'utilizzo di un'istanza di Point.

+2

È perfettamente ragionevole definire metodi che assomigliano a mutatori ma restituiscono una nuova istanza su un oggetto immutabile. Questa è una pratica di programmazione funzionale comune ed è anche un buon modo per scrivere Java thread-safe. –

1

Se si intende utilizzare Java e creare oggetti, quindi stilisticamente, penso che si dovrebbe cercare di sfruttare al massimo gli oggetti e l'incapsulamento dei dati. Per me, questo significa lasciare i dati dov'è (nella classe Point) e non passarli a un metodo separato per affrontarli. Fai lavorare i tuoi oggetti per te; non solo avere getter e setter. In effetti, pensa bene a come puoi evitare di aver bisogno di un getter.

È perfettamente comune avere metodi come add() e sottrarre() su una classe immutabile che restituisce nuove istanze della classe immutabile. Questo è un buon stile per la programmazione FP-like e perfettamente ragionevole per una classe come questa. (Vedi BigInteger o BigDecimal per buoni esempi. NON vedere Data o Calendario per esempi spaventosi di rotture sbagliate.:)

metodi Tenendo in classe consente di opzionalmente definiscono interfacce che queste classi possono implementare, utilizzare il decoratore o pattern Adapter, scrivere certi tipi di prove, ecc

0

Rendendoli statica rende anche più difficile per unità provali! L'unico sistema di simulazione che conosco in .NET che potrebbe gestire questo è TypeMock.

Se l'intenzione è quella di rendere questa classe immutabile, allora restituirai nuovi oggetti Punto in qualsiasi accessorio, chiama così renderli statici non ha molto senso qui.

Problemi correlati