Est-il judicieux d’avoir une méthode non statique qui n’utilise pas de variable d’instance?

Le compilateur ne permet pas à une méthode statique d’appeler une méthode non statique. Je comprends que c’est parce qu’une méthode non statique finit généralement par utiliser une variable d’instance.

Mais est-il judicieux d’avoir une méthode non statique qui n’utilise pas de variable d’instance? Si nous avons un comportement qui n’affecte pas ou n’est pas affecté par l’état de l’instance, une telle méthode ne devrait-elle pas être marquée comme statique.

    Souvent, non. Si la méthode ne touche aucun état d’instance, il n’y a aucune raison de la lier à une instance.

    Bien sûr, les méthodes statiques ne peuvent pas être héritées ni redéfinies, il est donc évident que vous souhaiterez avoir une méthode d’instance qui n’utilise pas l’état d’instance. Le modèle de stratégie en est un exemple classique.

    Il est également possible de lier une instance à une instance s’il s’agit d’une API publique et d’imaginer que vous souhaitiez lier la méthode à un état d’instance ultérieurement. Dans ce cas, les problèmes de compatibilité avec les versions antérieures des utilisateurs de votre API peuvent rendre difficile (voire impossible) la transformation de cette méthode statique en méthode d’instance.

    Et bien certainement! Supposons que vous avez dans l’ interface IMyCollection . Il a une méthode boolean isMutable() .

    Vous avez maintenant deux classes, la class MyMutableList et la class MyImmutableList , qui implémentent toutes les deux IMyCollection . Chacun d’entre eux remplacerait la méthode d’instance isMutable() , MyMutableList renvoyant simplement true et MyImmutableList renvoyant false .

    isMutable() dans les deux classes est une méthode d’instance qui (1) n’utilise pas de variables d’instance et (2) n’affecte pas l’état de l’instance. Cependant, en raison de contraintes dans le langage (impossible de remplacer les méthodes statiques), cette conception est la seule pratique.

    Aussi, je voudrais clarifier une idée fausse (comme l’a fait aussi @manouti): les méthodes non statiques ne sont pas des instances car elles utilisent des variables d’instance ou affectent l’état d’instance; Ce sont des méthodes d’instance car elles ont été définies de cette manière (sans le mot-clé static ) et ont donc un paramètre implicite (qui, dans les langages comme Python, est en fait explicite!).

    Comme les méthodes statiques ne peuvent pas être remplacées, de nombreux développeurs soucieux de la testabilité de leur code tentent d’éviter les méthodes statiques en Java.

    Le code est plus testable si les dépendances peuvent être remplacées par des objects simulés. Mockito et EasyMock sont les outils les plus courants pour y parvenir. Ils reposent sur l’inheritance pour créer des sous-classes qui vous permettent de remplacer facilement la méthode (souvent complexe) que vous ne souhaitez pas tester … pour que votre test soit ciblé sur ce que vous voulez tester.

    Je ne vais pas à l’extrême pour essayer des méthodes statiques, mais quand je concède de les inclure, je le regrette souvent plus tard, pour des raisons de test.

    Tout cela est très frustrant, car cela n’a rien à voir avec ce que devrait être la conception des méthodes statiques vs d’instance. Ce qui me donne envie pour ces langages qui vous permettent d’avoir des fonctions qui ne sont pas connectées à une classe …

    Si on écrivait une description lisible par l’homme du but de la méthode, cela ferait-il mention d’ un object? Si oui, utilisez une méthode d’instance. Sinon, utilisez une méthode statique. Notez que certaines méthodes peuvent être décrites de l’une ou l’autre manière, auquel cas il convient d’utiliser le jugement sur la signification qui est la meilleure.

    Considérez, par exemple, “Obtenez l’adresse à laquelle un formulaire d’impôt sur le revenu de la Freedonian doit être envoyé” vs “Obtenez l’adresse à laquelle les formulaires de l’impôt sur le revenu de la Freedonian doivent être envoyés”? La première question devrait recevoir une réponse par une méthode d’instance; la seconde par une méthode statique. Il se peut que Freedonia exige actuellement que tous les formulaires fiscaux soient envoyés à la même adresse (auquel cas la première méthode pourrait ignorer tous les champs d’instance), mais qu’à l’avenir, les bureaux des différentes régions pourraient être différents ( pourrait regarder l’ID du consortingbuable et sélectionner une adresse postale en fonction de cela, alors que la dernière méthode devrait diriger les formulaires vers un bureau qui pourrait accepter les formulaires pour n’importe qui et les redirect si nécessaire.

    Je comprends que c’est parce qu’une méthode non statique finit généralement par utiliser une variable d’instance.

    Même si la méthode d’instance n’utilise pas de variable d’instance, elle est toujours liée à l’instance de la classe. En fait, cela a une référence implicite dans les arguments de la méthode.

    En d’autres termes, dans la méthode suivante:

     public void foo() { } 

    this est implicitement passé en tant que première variable locale de la méthode.

    MODIFIER:

    Relisant la question, il s’agit plutôt d’une question large qui dépend de la situation. Généralement, si la méthode n’a pas besoin de l’instance (et vous êtes presque sûr que ce ne sera pas le cas), alors restz static .

    Un bon exemple est un codage de booléens orienté object. La plupart des langages, même ceux orientés object comme Java, optent pour un codage des booléens orienté Type de données abstraites, mais Smalltalk utilise par exemple un codage OO, et presque aucune des méthodes n’utilise un état d’instance. Cela ressemble un peu à ceci:

     import java.util.function.Supplier; @FunctionalInterface interface Block { void call(); } interface Bool { Bool not(); Bool and(Bool other); Bool or(Bool other);  T ifThenElse(Supplier thenBranch, Supplier elseBranch); void ifThenElse(Block thenBranch, Block elseBranch); static final Bool T = new TrueClass(); static final Bool F = new FalseClass(); class TrueClass implements Bool { public Bool not() { return F; } public Bool and(Bool other) { return other; } public Bool or(Bool other) { return this; } public  T ifThenElse(Supplier thenBranch, Supplier elseBranch) { return thenBranch.get(); } public void ifThenElse(Block thenBranch, Block elseBranch) { thenBranch.call(); } } class FalseClass implements Bool { public Bool not() { return T; } public Bool and(Bool other) { return this; } public Bool or(Bool other) { return other; } public  T ifThenElse(Supplier thenBranch, Supplier elseBranch) { return elseBranch.get(); } public void ifThenElse(Block thenBranch, Block elseBranch) { elseBranch.call(); } } } public class Main { public static void main(Ssortingng... args) { Bool.F.ifThenElse(() -> System.out.println("True"), () -> System.out.println("False")); // False } } 

    En fait, si vous suivez un engagement sérieux envers OO, utilisez beaucoup de méthodes référentiellement transparentes et préférez le polymorphism aux conditions, vous vous retrouverez souvent avec des méthodes dans beaucoup de sous-classes, où chaque implémentation dans l’une des classes renvoie une valeur constante .

    Je pense que parfois, c’est oui, car une méthode non statique peut remplacer différentes tâches pour une classe différente, mais la tâche peut ne pas impliquer de variable d’instance, par exemple:

    Fruit.java

     public class Fruit{ public void printInfo(){ System.out.println("This is fruit"); } } 

    Orange.java

     public class Orange extends Fruit{ public void printInfo(){ System.out.println("This is orange"); } } 

    Grape.java

     public class Grape extends Fruit{ public void printInfo(){ System.out.println("This is grape"); } } 

    informations d’impression de l’object:

     Fruit f=new Grape(); f.printInfo();