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.