Pourquoi ne puis-je pas déclarer des méthodes statiques dans une interface?

Le sujet en dit long: quelle est la raison pour laquelle les méthodes statiques ne peuvent pas être déclarées dans une interface?

public interface ITest { public static Ssortingng test(); } 

Le code ci-dessus me donne l’erreur suivante (dans Eclipse, au moins): “Modificateur non conforme pour la méthode d’interface ITest.test (); seul public & abstract est autorisé”.

Il y a quelques problèmes en jeu ici. Le premier est la question de la déclaration d’une méthode statique sans la définir. C’est la différence entre

 public interface Foo { public static int bar(); } 

et

 public interface Foo { public static int bar() { ... } } 

Le premier est impossible pour les raisons mentionnées par Espo : vous ne savez pas quelle classe d’implémentation est la définition correcte.

Java pourrait autoriser ce dernier; et en fait, à partir de Java 8, c’est le cas!

La raison pour laquelle vous ne pouvez pas avoir de méthode statique dans une interface réside dans la manière dont Java résout les références statiques. Java ne prendra pas la peine de rechercher une instance d’une classe lors de la tentative d’exécution d’une méthode statique. En effet, les méthodes statiques ne dépendent pas de l’instance et peuvent donc être exécutées directement à partir du fichier de classe. Étant donné que toutes les méthodes d’une interface sont abstraites, la machine virtuelle devrait rechercher une implémentation particulière de l’interface afin de trouver le code derrière la méthode statique afin de pouvoir l’exécuter. Cela contredit alors le fonctionnement de la résolution de la méthode statique et introduirait une incohérence dans le langage.

Je vais répondre à votre question avec un exemple. Supposons que nous ayons une classe Math avec une méthode d’ajout de méthode statique. Vous appelez cette méthode comme suit:

 Math.add(2, 3); 

Si Math était une interface au lieu d’une classe, il ne pourrait pas avoir de fonctions définies. En tant que tel, dire quelque chose comme Math.add (2, 3) n’a aucun sens.

La raison réside dans le principe de conception, à savoir que Java ne permet pas l’inheritance multiple. Le problème de l’inheritance multiple peut être illustré par l’exemple suivant:

 public class A { public method x() {...} } public class B { public method x() {...} } public class C extends A, B { ... } 

Maintenant, que se passe-t-il si vous appelez Cx ()? Sera Ax () ou Bx () exécuté? Chaque langage à inheritance multiple doit résoudre ce problème.

Les interfaces permettent en Java une sorte d’inheritance multiple restreint. Pour éviter le problème ci-dessus, ils ne sont pas autorisés à avoir des méthodes. Si nous examinons le même problème avec les interfaces et les méthodes statiques:

 public interface A { public static method x() {...} } public interface B { public static method x() {...} } public class C implements A, B { ... } 

Même problème ici, que se passe-t-il si vous appelez Cx ()?

Les méthodes statiques ne sont pas des méthodes d’instance. Il n’y a pas de contexte d’instance, donc l’implémenter depuis l’interface n’a pas beaucoup de sens.

Maintenant, Java8 nous permet de définir des méthodes statiques dans Interface.

 interface X { static void foo() { System.out.println("foo"); } } class Y implements X { //... } public class Z { public static void main(Ssortingng[] args) { X.foo(); // Y.foo(); // won't comstack because foo() is a Static Method of X and not Y } } 

Note: Les méthodes dans Interface sont toujours publiques par défaut si nous n’utilisons pas explicitement les mots-clés default / static pour les rendre Defender et Static resp.

Il y a une réponse très belle et concise à votre question ici . (Cela m’a semblé une manière si simple de l’expliquer que je veux la lier d’ici.)

Il semble que la méthode statique de l’interface puisse être prise en charge dans Java 8 , ma solution est simplement de les définir dans la classe interne.

 interface Foo { // ... class fn { public static void func1(...) { // ... } } } 

La même technique peut également être utilisée dans les annotations:

 public @interface Foo { Ssortingng value(); class fn { public static Ssortingng getValue(Object obj) { Foo foo = obj.getClass().getAnnotation(Foo.class); return foo == null ? null : foo.value(); } } } 

La classe interne devrait toujours être accessible sous la forme d’ Interface.fn... au lieu de Class.fn... , alors, vous pouvez vous débarrasser d’un problème ambigu.

Une interface est utilisée pour le polymorphism, qui s’applique aux objects, pas aux types. Par conséquent (comme déjà noté), cela n’a aucun sens d’avoir un membre d’interface statique.

Java 8 Si vous aviez changé le monde, vous pouvez avoir des méthodes statiques dans l’interface, mais cela vous oblige à fournir une implémentation pour cela.

 public interface StaticMethodInterface { public static int testStaticMethod() { return 0; } /** * Illegal combination of modifiers for the interface method * testStaticMethod; only one of abstract, default, or static permitted * * @param i * @return */ // public static abstract int testStaticMethod(float i); default int testNonStaticMethod() { return 1; } /** * Without implementation. * * @param i * @return */ int testNonStaticMethod(float i); 

}

Combinaison illégale de modificateurs: statique et abstrait

Si un membre d’une classe est déclaré comme statique, il peut être utilisé avec son nom de classe qui est limité à cette classe, sans créer d’object.

Si un membre d’une classe est déclaré comme abstrait, vous devez déclarer la classe comme abstrait et vous devez fournir l’implémentation du membre abstrait dans sa classe héritée (sous-classe).

Vous devez fournir une implémentation au membre abstrait d’une classe dans la sous-classe où vous allez changer le comportement de la méthode statique, également déclarée comme abstraite, confinée à la classe de base, ce qui n’est pas correct

Puisque les méthodes statiques ne peuvent pas être héritées. Donc inutile de le placer dans l’interface. L’interface est fondamentalement un contrat que tous ses abonnés doivent suivre. Placer une méthode statique dans l’interface obligera les abonnés à l’implémenter. ce qui devient désormais contradictoire au fait que les méthodes statiques ne peuvent pas être héritées.

Peut-être un exemple de code serait utile, je vais utiliser C #, mais vous devriez pouvoir suivre.

Supposons que nous avons une interface appelée IPayable

 public interface IPayable { public Pay(double amount); } 

Maintenant, nous avons deux classes concrètes qui implémentent cette interface:

 public class BusinessAccount : IPayable { public void Pay(double amount) { //Logic } } public class CustomerAccount : IPayable { public void Pay(double amount) { //Logic } } 

Maintenant, supposons que nous avons une collection de comptes différents, pour cela nous utiliserons une liste générique du type IPayable

 List accountsToPay = new List(); accountsToPay.add(new CustomerAccount()); accountsToPay.add(new BusinessAccount()); 

Maintenant, nous voulons payer 50,00 $ à tous ces comptes:

 foreach (IPayable account in accountsToPay) { account.Pay(50.00); } 

Alors maintenant, vous voyez comment les interfaces sont incroyablement utiles.

Ils ne sont utilisés que sur des objects instanciés. Pas sur les classes statiques.

Si vous avez effectué un paiement statique, lors de la lecture en boucle du fichier IPayable dans accountsToPay, il n’y aurait aucun moyen de savoir s’il devrait appeler pay sur BusinessAcount ou CustomerAccount.