Perché passare oggetti attraverso metodi statici sarebbe vantaggioso?


9

Perché ci sarebbe un vantaggio nell'utilizzare un metodo statico e passare il riferimento a un oggetto come parametro piuttosto che chiamare il metodo su un oggetto?

Per chiarire cosa intendo, considera la seguente classe:

public class SomeClass {
    private double someValue;

    public SomeClass() {
        // Some constructor in which someValue is set
    }

    public void incrementValue() {
        someValue++;
    }
}

Rispetto a questa implementazione alternativa con un metodo statico:

public class SomeClass {
    private double someValue;

    public SomeClass() {
        // Some constructor in which someValue is set
    }

    public static void incrementValue(SomeClass obj) {
        obj.someValue++;
    }
}

La mia domanda non è limitata a questa sola classe; qualsiasi punto in cui passeresti un oggetto invece di chiamarlo su un metodo è ciò che mi interessa. È mai vantaggioso? Se è così, perché?


1
Sembra un odore di codice con due metodi che fanno esattamente la stessa cosa. Se il metodo statico fosse semplicemente delegato all'altro metodo, allora sembrerebbe inutile, ma non necessariamente "cattivo"
— Nathan Merrill

13
@NathanMerrill Penso che ti stia perdendo il punto. Sta chiedendo se c'è mai una situazione in cui sarebbe preferibile creare e usare il secondo metodo anziché il primo metodo.

@Mego Non solo i metodi indicati nell'esempio; Sto chiedendo se c'è qualche momento in cui usare metodi statici e passare oggetti è meglio che chiamare metodi su oggetti?
— Addison Crump,

Presumibilmente stai chiedendo specificamente java?
— Enderland

3
Penso che questa domanda faccia presupporre tacitamente che il codice orientato agli oggetti sia una specie di ottimale. Un approccio più procedurale o funzionale porterebbe naturalmente all'uso di metodi statici. ... La duplicazione della funzionalità tra un metodo statico e un metodo di istanza è piuttosto stupida, però. Spero che sia solo un esempio e il codice reale di cui stai parlando ha solo statico.
— jpmc26,

Risposte:


34

Un esempio banale: quando l'istanza passata può legittimamente essere nulla e si desidera incorporare la gestione (non banale) di questo nel metodo.


1
esempio: String.Compare in C # (penso che ci sia qualcosa di simile in Java)
— edc65

Objects.equals () e Objects.compare () sono esempi in Java, ma non fanno parte della classe originale. Nella libreria standard di Java, almeno, è comune avere un metodo di istanza su qualcosa come oggetto, ma poi un metodo statico su un oggetto s di classe.
— daboross,

20

Nel tuo esempio, il metodo di istanza è un chiaro vincitore.

Nel caso generale, posso pensare ad alcuni motivi per cui un metodo statico potrebbe essere appropriato:

  • Vuoi mettere il metodo statico in un'altra classe, poiché hai una situazione in cui ha senso separare la logica dai dati (nota: il tuo esempio non è uno di questi).

  • Stai passando due o più oggetti e vuoi sottolineare che sono di uguale importanza.

  • null è un valore valido (come spiegato dall'utente 9000).


5

Sarebbe saggio includere i metodi che cambiano lo stato dell'oggetto come metodi di istanza piuttosto che come metodo statico .

Tuttavia, possiamo trovare esempi di metodi statici che sono puremetodi e prendono l'oggetto come input, ad esempio quando è necessario creare un'istanza dell'oggetto in base a determinate regole di convalida. Ad esempio, .NET ha il metodo DateTime.TryParse(String s, DateTime d)per convalidare e creare un'istanza dell'oggetto. Ma il parametro DateTime dè esplicitamente contrassegnato come out.

Un altro caso può essere quando confrontiamo gli oggetti e vogliamo ottenere l'oggetto desiderato come valore di ritorno anziché come valore booleano / intero del risultato del confronto, ad esempio Team.GetHigherScorer(teamA, teamB).IncreaseRanking(). Questo sarà più pulito di:

int compareResult = teamA.compareScoreWith(teamB);
if (compareResult == 1)
    teamA.IncreaseRanking();
else if (compareResult == -1) 
    teamB.IncreaseRanking();

(lasciando il caso "disegnare" per semplicità).


1
Non si passa un "intero oggetto". Si passa il riferimento a un posto in memoria, che è una quantità molto piccola di dati che vengono passati. Non sono sicuro dell'effetto sulle prestazioni che ha, ma tuttavia ... cosa implica la marcatura "out"?
— Addison Crump,

1
Ho lasciato cadere la parola "intero" dalla mia affermazione, era confusa. Non ho mai inteso prestazioni o dimensioni, la risposta si basa esclusivamente su pratiche di programmazione. Ad ogni modo, outè una .Netparola chiave utilizzata come modificatore di parametri. Indica che il parametro viene passato per riferimento. Vedi per i dettagli msdn.microsoft.com/en-us/library/t3c3bfhx.aspx~~V~~plural~~3rd
— wonderbell

4
La prima frase è semplicemente sbagliata. se abbiamo class C { int x; static void M() { allora M è perfettamente in grado di accedere x. Ad esempio int y = (new C()).x;è legale.
— Eric Lippert,

@EricLippert :) Sono sicuro che sai cosa intendevo dire. È incredibile come i maestri possano leggere tra le righe. Potrebbe essere necessario modificare quella frase. Per chiarimenti, qualcosa del genere static void M() { this.x = 1; }non è possibile.
— Wonderbell,

1
@wonderbell: No, sono sicuro di non sapere cosa intendevi. Sapevo cosa hai scritto. Prendo atto che non this.xè sbagliato perché xnon è possibile accedervi ma perché thisnon esiste. Non è affatto una questione di accesso , è una questione di esistenza .
— Eric Lippert,

4

L'iniezione di dipendenza sarebbe un buon motivo per eseguire la chiamata al metodo statico. Supponendo che l'implementazione concreta di SomeClassabbia una catena di eredità o sia l'implementazione di un'altra classe. È possibile utilizzare una derisione di un oggetto, passarlo a scopo di test per assicurarsi che il metodo faccia quello che dovrebbe, e quindi riporta tale stato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.