Pourquoi le passage d'objets par des méthodes statiques serait-il avantageux?

9

Pourquoi y aurait-il un avantage à utiliser une méthode statique et à passer la référence à un objet en tant que paramètre plutôt que d'appeler la méthode sur un objet?

Pour clarifier ce que je veux dire, considérez la classe suivante:

public class SomeClass {
    private double someValue;

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

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

Par rapport à cette implémentation alternative avec une méthode statique:

public class SomeClass {
    private double someValue;

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

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

Ma question ne se limite pas à cette seule classe; n'importe quel point où vous passeriez un objet au lieu de l'appeler sur une méthode est ce qui m'intéresse. Est-ce jamais avantageux? Si oui, pourquoi?

Addison Crump
la source
1
Cela ressemble à une odeur de code avec deux méthodes faisant exactement la même chose. Si la méthode statique était simplement déléguée à l'autre méthode, elle se sentirait inutile, mais pas nécessairement "mauvaise"
Nathan Merrill
13
@NathanMerrill Je pense que vous manquez le point. Il demande s'il y a jamais une situation où la création et l'utilisation de la deuxième méthode au lieu de la première méthode seraient préférables.
@Mego Non seulement les méthodes données dans l'exemple; Je demande s'il y a un moment où il est préférable d'utiliser des méthodes statiques et de passer des objets que d'appeler des méthodes sur des objets?
Addison Crump
Vraisemblablement, vous demandez spécifiquement pour Java?
enderland
3
Je pense que cette question fait une supposition tacite que le code orienté objet est une sorte d'optimum. Une approche plus procédurale ou fonctionnelle conduirait naturellement à l'utilisation de méthodes statiques. ... Dupliquer la fonctionnalité entre une méthode statique et une méthode d'instance est cependant assez idiot. J'espère que ce n'est qu'un exemple et que le code dont vous parlez n'a que du statique.
jpmc26

Réponses:

34

Un exemple trivial: lorsque l'instance transmise peut légitimement être nulle et que vous souhaitez incorporer la gestion (non triviale) de cela dans la méthode.

9000
la source
1
exemple: String.Compare en C # (je pense qu'il y a quelque chose de similaire en Java)
edc65
Objects.equals () et Objects.compare () sont des exemples en Java - mais ils ne font pas partie de la classe d'origine. Dans la bibliothèque standard Java au moins, il est fréquent d'avoir une méthode d'instance sur quelque chose comme objet, mais une méthode statique sur un objet de la classe.
daboross
20

Dans votre exemple, la méthode d'instance est clairement gagnante.

Dans le cas général, je peux penser à quelques raisons pour lesquelles une méthode statique pourrait être appropriée:

  • Vous voulez mettre la méthode statique dans une autre classe, car vous avez une situation où il est logique de séparer la logique des données (remarque: votre exemple n'est pas l'un d'eux).

  • Vous passez deux ou plusieurs objets et vous voulez souligner qu'ils sont d'égale importance.

  • null est une valeur valide (comme expliqué par l'utilisateur 9000).

Heinzi
la source
5

Il serait judicieux d'inclure les méthodes qui modifient l'état de l'objet en tant que méthodes d' instance plutôt qu'en tant que méthode statique .

Cependant, nous pouvons trouver des exemples de méthodes statiques qui sont des pureméthodes et prennent l'objet en entrée, comme lorsque nous devons instancier l'objet en fonction de certaines règles de validation. Par exemple, .NET a la méthode DateTime.TryParse(String s, DateTime d)pour valider et instancier l'objet. Mais le paramètre DateTime dest explicitement marqué comme out.

Un autre cas peut être lorsque nous comparons les objets et que nous voulons obtenir l'objet souhaité comme valeur de retour plutôt qu'une valeur booléenne / entière du résultat de la comparaison, par exemple Team.GetHigherScorer(teamA, teamB).IncreaseRanking(),. Ce sera plus propre que:

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

(laissant le cas "tirer" pour plus de simplicité).

Wonderbell
la source
1
On ne passe pas un "objet entier". Vous passez la référence à un endroit en mémoire, qui est une très petite quantité de données transmises. Je ne suis pas sûr de l'effet que cela a sur les performances, mais néanmoins ... aussi, qu'est-ce que le marquage "out" implique?
Addison Crump,
1
J'ai laissé tomber le mot «entier» de ma déclaration, c'était déroutant. Je n'ai jamais voulu de performances ou de taille, la réponse est purement basée sur des pratiques de programmation. Quoi qu'il en soit, outest un .Netmot - clé utilisé comme modificateur de paramètre. Il indique que le paramètre est transmis par référence. Voir pour plus de détails msdn.microsoft.com/en-us/library/t3c3bfhx.aspx
wonderbell
4
La première phrase est tout simplement fausse. si nous avons class C { int x; static void M() { alors M est parfaitement en mesure d'accéder x. Par exemple, int y = (new C()).x;c'est légal.
Eric Lippert
@EricLippert :) Je suis sûr que vous savez de quoi je parle. C'est incroyable de voir comment les maîtres peuvent lire entre les lignes. Peut-être ai-je besoin de modifier cette phrase. Pour clarification, quelque chose comme ça static void M() { this.x = 1; }n'est pas possible.
wonderbell
1
@wonderbell: Non, je suis sûr que je ne savais pas ce que tu voulais dire. Je savais ce que tu as écrit. Je note que this.xc'est faux non pas parce xqu'on ne peut pas y accéder mais parce qu'il thisn'existe pas. Ce n'est pas du tout une question d' accès , c'est une question d' existence .
Eric Lippert
4

L'injection de dépendances serait une bonne raison d'effectuer l'appel à la méthode statique. En supposant que l'implémentation concrète de SomeClasspossède une chaîne d'héritage ou soit l'implémentation d'une autre classe. Vous pouvez utiliser une maquette d'un objet, la transmettre à des fins de test pour vous assurer que votre méthode fait ce qu'elle est censée faire, puis rendre compte de cet état.

Adam Zuckerman
la source