Pourquoi ne puis-je pas définir une méthode statique dans une interface Java?


499

EDIT: Depuis Java 8, les méthodes statiques sont désormais autorisées dans les interfaces.

Voici l'exemple:

public interface IXMLizable<T>
{
  static T newInstanceFromXML(Element e);
  Element toXMLElement();
}

Bien sûr, cela ne fonctionnera pas. Mais pourquoi pas?

L'un des problèmes possibles serait ce qui se passe lorsque vous appelez:

IXMLizable.newInstanceFromXML(e);

Dans ce cas, je pense qu'il devrait simplement appeler une méthode vide (ie {}). Toutes les sous-classes seraient obligées d'implémenter la méthode statique, donc elles iraient toutes bien lors de l'appel de la méthode statique. Alors pourquoi cela n'est-il pas possible?

EDIT: Je suppose que je cherche une réponse plus profonde que «parce que c'est comme ça que Java est».

Y a-t-il une raison technologique particulière pour laquelle les méthodes statiques ne peuvent pas être écrasées? Autrement dit, pourquoi les concepteurs de Java ont-ils décidé de rendre les méthodes d'instance remplaçables mais pas les méthodes statiques?

EDIT: Le problème avec ma conception est que j'essaie d'utiliser des interfaces pour appliquer une convention de codage.

Autrement dit, l'objectif de l'interface est double:

  1. Je veux que l'interface IXMLizable me permette de convertir des classes qui l'implémentent en éléments XML (en utilisant le polymorphisme, ça marche bien).

  2. Si quelqu'un veut créer une nouvelle instance d'une classe qui implémente l'interface IXMLizable, il saura toujours qu'il y aura un constructeur statique newInstanceFromXML (Element e).

Existe-t-il un autre moyen de garantir cela, autre que de simplement mettre un commentaire dans l'interface?


4
Vous n'avez pas besoin d'encombrer les définitions de méthode (et de champ) avec public dans les interfaces, btw.
Tom Hawtin - tackline

Hmm, semble être un doublon de stackoverflow.com/questions/21817/… . Je n'avais jamais vu ça auparavant.
Michael Myers

1
Pourriez-vous fournir du code comment aimeriez-vous utiliser des méthodes d'interface statiques?
Pavel Feldman

43
Cela sera possible dans Java 8: docs.oracle.com/javase/tutorial/java/IandI/…
dakshang

1
@dakshang Oui, mais il ne fait pas ce que souhaite le PO.
user253751

Réponses:


518

Java 8 autorise les méthodes d'interface statique

Avec Java 8, les interfaces peuvent avoir des méthodes statiques. Ils peuvent également avoir des méthodes d'instance concrètes, mais pas des champs d'instance.

Il y a vraiment deux questions ici:

  1. Pourquoi, dans le mauvais vieux temps, les interfaces ne pouvaient-elles pas contenir de méthodes statiques?
  2. Pourquoi les méthodes statiques ne peuvent-elles pas être remplacées?

Méthodes statiques dans les interfaces

Il n'y avait aucune raison technique solide pour laquelle les interfaces n'auraient pas pu avoir de méthodes statiques dans les versions précédentes. Ceci est bien résumé par l'affiche d'une question en double. Les méthodes d'interface statique étaient initialement considérées comme un petit changement de langage, puis il y a eu une proposition officielle de les ajouter dans Java 7, mais elles ont été abandonnées par la suite en raison de complications imprévues.

Enfin, Java 8 a introduit des méthodes d'interface statique, ainsi que des méthodes d'instance remplaçables avec une implémentation par défaut. Cependant, ils ne peuvent toujours pas avoir de champs d'instance. Ces fonctionnalités font partie de la prise en charge de l'expression lambda, et vous pouvez en savoir plus à leur sujet dans la partie H de JSR 335.

Remplacement des méthodes statiques

La réponse à la deuxième question est un peu plus compliquée.

Les méthodes statiques peuvent être résolues au moment de la compilation. La répartition dynamique est logique pour les méthodes d'instance, où le compilateur ne peut pas déterminer le type concret de l'objet et, par conséquent, ne peut pas résoudre la méthode à appeler. Mais invoquer une méthode statique nécessite une classe, et puisque cette classe est connue statiquement - au moment de la compilation - la répartition dynamique n'est pas nécessaire.

Un petit historique sur le fonctionnement des méthodes d'instance est nécessaire pour comprendre ce qui se passe ici. Je suis sûr que l'implémentation réelle est assez différente, mais permettez-moi d'expliquer ma notion de répartition des méthodes, qui modélise avec précision le comportement observé.

Imaginez que chaque classe possède une table de hachage qui mappe les signatures de méthode (noms et types de paramètres) à un morceau de code réel pour implémenter la méthode. Lorsque la machine virtuelle tente d'appeler une méthode sur une instance, elle interroge l'objet pour sa classe et recherche la signature demandée dans la table de la classe. Si un corps de méthode est trouvé, il est appelé. Sinon, la classe parente de la classe est obtenue et la recherche y est répétée. Cela continue jusqu'à ce que la méthode soit trouvée, ou qu'il n'y ait plus de classes parentes - ce qui entraîne unNoSuchMethodError .

Si une superclasse et une sous-classe ont toutes deux une entrée dans leurs tables pour la même signature de méthode, la version de la sous-classe est rencontrée en premier et la version de la superclasse n'est jamais utilisée - il s'agit d'une "substitution".

Supposons maintenant que nous ignorions l'instance d'objet et commençons simplement par une sous-classe. La résolution pourrait continuer comme ci-dessus, vous donnant une sorte de méthode statique "surchargeable". La résolution peut cependant se produire au moment de la compilation, car le compilateur démarre à partir d'une classe connue, plutôt que d'attendre jusqu'à l'exécution pour interroger un objet d'un type non spécifié pour sa classe. Il ne sert à rien de "remplacer" une méthode statique car on peut toujours spécifier la classe qui contient la version souhaitée.


"Interfaces" constructeur

Voici un peu plus de matériel pour répondre à la récente modification de la question.

Il semble que vous souhaitiez mandater efficacement une méthode de type constructeur pour chaque implémentation de IXMLizable. Oubliez d'essayer d'appliquer cela avec une interface pendant une minute et prétendez que vous avez des classes qui répondent à cette exigence. Comment l'utiliseriez-vous?

class Foo implements IXMLizable<Foo> {
  public static Foo newInstanceFromXML(Element e) { ... }
}

Foo obj = Foo.newInstanceFromXML(e);

Comme vous devez nommer explicitement le type concret Foolors de la "construction" du nouvel objet, le compilateur peut vérifier qu'il possède bien la méthode d'usine nécessaire. Et si ce n'est pas le cas, alors quoi? Si je peux mettre en œuvre un IXMLizablequi n'a pas le « constructeur », et je créer une instance et le transmettre à votre code, il est unIXMLizable avec toute l'interface nécessaire.

La construction fait partie de l'implémentation, pas de l'interface. Tout code qui fonctionne correctement avec l'interface ne se soucie pas du constructeur. Tout code qui se soucie du constructeur doit de toute façon connaître le type concret, et l'interface peut être ignorée.



12
La raison n ° 1 pourrait-elle être l'héritage multiple? Étant donné que nous pouvons hériter de plusieurs interfaces, si deux interfaces contenaient la même signature de méthode statique et qu'une classe les implémentait toutes les deux et appelait cette méthode, les choses pourraient se compliquer d'une manière que les créateurs de langage Java voulaient éviter en interdisant l'héritage de plusieurs classes dans la première place. Le même argument pourrait évidemment être avancé pour que l'interface ne permette aucune définition de méthode.
shrini1000

1
@ shrini1000 - Non, les méthodes statiques sont résolues au moment de la compilation. L'ambiguïté peut être gérée de la même manière qu'avec les constantes: avec une erreur de compilation. Cependant, la proposition du projet Coin a été rejetée, invoquant des difficultés imprévues. Je ne sais pas exactement ce que c'était, mais je ne pense pas que ce soit dans ce sens.
erickson

1
@ tgm1024 Oui, la section "Constructeurs" interfaces "" explique pourquoi cela n'a pas de sens d'essayer d'invoquer un comportement polymorphe via un type connu au moment de la compilation. Comment invoqueriez-vous RESET()une classe donnée? Vous écririez SomeClass.RESET(). Vous n'avez donc pas besoin d'une interface pour décrire cette API; son statique. Les interfaces sont utilisées lorsque vous ne connaissez pas le type de béton au moment de la compilation. Ce n'est jamais le cas avec une méthode statique.
erickson

2
"La construction fait partie de l'implémentation, pas de l'interface. Tout code qui fonctionne correctement avec l'interface ne se soucie pas du constructeur." - Ce n'est clairement pas vrai. Dans d'autres langages (par exemple Swift), je peux créer de nouvelles instances de Tsans savoir Tstatiquement, car je promets dans une interface qu'un certain constructeur (ou méthode statique) existera au moment de l'exécution. Le fait que la génération soit impossible à spécifier en Java ne signifie pas que ce n'est pas une chose significative à faire.
Raphael

48

Cela a déjà été demandé et répondu, ici

Pour dupliquer ma réponse:

Il ne sert à rien de déclarer une méthode statique dans une interface. Ils ne peuvent pas être exécutés par l'appel normal MyInterface.staticMethod (). Si vous les appelez en spécifiant la classe d'implémentation MyImplementor.staticMethod (), vous devez alors connaître la classe réelle, il est donc sans importance que l'interface la contienne ou non.

Plus important encore, les méthodes statiques ne sont jamais remplacées, et si vous essayez de le faire:

MyInterface var = new MyImplementingClass();
var.staticMethod();

les règles pour statique disent que la méthode définie dans le type déclaré de var doit être exécutée. Comme il s'agit d'une interface, cela est impossible.

La raison pour laquelle vous ne pouvez pas exécuter "result = MyInterface.staticMethod ()" est qu'il devrait exécuter la version de la méthode définie dans MyInterface. Mais il ne peut pas y avoir de version définie dans MyInterface, car c'est une interface. Il n'a pas de code par définition.

Bien que vous puissiez dire que cela revient à "parce que Java le fait de cette façon", en réalité, la décision est une conséquence logique d'autres décisions de conception, également prises pour une très bonne raison.


14
Si vous utilisez <T étend MyInterface> comme paramètre de type générique, il serait bien de garantir via l'interface que T peut .doSomething ().
Chris Betti

4
Bien que je comprenne les arguments, je suis d'accord avec @Chris_Betti (même pour les types non génériques): ce serait bien que la structure de code garantisse que certaines classes implémentent une API statique spécifique. Peut-être que c'est possible en utilisant un concept différent ...
Juh_

@Juh_, ..... ou un nouveau mot-clé si absolument nécessaire. Je crois que staticc'est un terme minable dans les langues de toute façon, et a été trop étendu tel quel. Donc, l'avoir en soi est déjà sommaire. Voir mon exemple ci-dessus stackoverflow.com/questions/512877/… {haussement d'épaules}.

3
Cela semble faux: "Il ne sert à rien de déclarer une méthode statique dans une interface." Si j'ai une collection de classes qui, sans être instanciée, pourrait m'offrir des informations mais j'aurais besoin d'une interface commune pour mettre ces informations statiques au niveau de la classe (c'est-à-dire une interface avec une méthode statique redéfinissable) alors c'est une utilisation valide . Pensez à la réflexion ++, où vous pouvez capturer des méta-informations sur les propriétés de classe sans pirater avec des attributs, de la réflexion, etc.
Jason

1
"Il ne sert à rien de déclarer une méthode statique dans une interface." Ce n'est pas vrai: imaginez que votre système dispose d'un résolveur de classe par défaut. S'il détecte que vous implémentez la méthode ContainerInjectionInterce :: create (Container $ container), il créera par exemple l'objet avec cette fonction.
user3790897

37

Normalement, cela se fait en utilisant un modèle d'usine

public interface IXMLizableFactory<T extends IXMLizable> {
  public T newInstanceFromXML(Element e);
}

public interface IXMLizable {
  public Element toXMLElement();
}

7
+1 un modèle d'usine semble être la solution au problème. (mais pas à la question)
pvgoddijn

Quelqu'un peut-il me dire quel est le sens de mettre <T étend IXMLizable> ici. Je suis nouveau sur java. Que fait-il?
Nuwan Harshakumara Piyarathna

1
@NuwanHarshakumaraPiyarathna T doit être une classe étendant IXMLizable. Examinez les génériques Java pour mieux comprendre ce que cela signifie
adrian

37

Avec l'avènement de Java 8, il est désormais possible d'écrire des méthodes par défaut et statiques dans l'interface. docs.oracle/staticMethod

Par exemple:

public interface Arithmetic {

    public int add(int a, int b);

    public static int multiply(int a, int b) {
        return a * b;
    }
}
public class ArithmaticImplementation implements Arithmetic {

    @Override
    public int add(int a, int b) {
        return a + b;
    }

    public static void main(String[] args) {
        int result = Arithmetic.multiply(2, 3);
        System.out.println(result);
    }
}

Résultat : 6

CONSEIL: L' appel d'une méthode d'interface statique ne nécessite aucune implémentation par aucune classe. Cela se produit sûrement parce que les mêmes règles pour les méthodes statiques dans les superclasses s'appliquent aux méthodes statiques sur les interfaces.


Ceci est un parfait exemple de cette question.

21

Parce que les méthodes statiques ne peuvent pas être remplacées dans les sous-classes, et donc elles ne peuvent pas être abstraites. Et toutes les méthodes d'une interface sont, de facto , abstraites.


2
Vous pouvez toujours forcer chaque type à implémenter des méthodes d'interface statiques. Classes, quelqu'un?
MichaelGG

16
Sortez de vous-même et répondez à la question: pourquoi une méthode statique ne peut-elle pas être remplacée? Si les méthodes statiques pouvaient être remplacées, à quoi ressemblerait-elle? Que pourriez-vous en faire? Cette réponse est essentiellement "Vous ne pouvez pas parce que vous ne pouvez pas."
erickson

10

Pourquoi ne puis-je pas définir une méthode statique dans une interface Java?

En fait, vous pouvez en Java 8.

Selon le document Java :

Une méthode statique est une méthode associée à la classe dans laquelle elle est définie plutôt qu'à n'importe quel objet. Chaque instance de la classe partage ses méthodes statiques

Dans Java 8, une interface peut avoir des méthodes par défaut et des méthodes statiques . Cela nous permet d'organiser plus facilement les méthodes d'assistance dans nos bibliothèques. Nous pouvons conserver des méthodes statiques spécifiques à une interface dans la même interface plutôt que dans une classe distincte.

Exemple de méthode par défaut:

list.sort(ordering);

au lieu de

Collections.sort(list, ordering);

Exemple de méthode statique (du doc lui-même):

public interface TimeClient {
    // ...
    static public ZoneId getZoneId (String zoneString) {
        try {
            return ZoneId.of(zoneString);
        } catch (DateTimeException e) {
            System.err.println("Invalid time zone: " + zoneString +
                "; using default time zone instead.");
            return ZoneId.systemDefault();
        }
    }

    default public ZonedDateTime getZonedDateTime(String zoneString) {
        return ZonedDateTime.of(getLocalDateTime(), getZoneId(zoneString));
    }    
}

6

Les interfaces concernent le polymorphisme qui est intrinsèquement lié aux instances d'objet, pas aux classes. Par conséquent, statique n'a pas de sens dans le contexte d'une interface.


Logique claire et concise. Bien placé.
Oke Uwechue du

6

Premièrement, toutes les décisions linguistiques sont des décisions prises par les créateurs de langues. Il n'y a rien dans le monde du génie logiciel ou de la définition de langage ou de l'écriture du compilateur / interprète qui dit qu'une méthode statique ne peut pas faire partie d'une interface. J'ai créé quelques langages et écrit des compilateurs pour eux - tout cela ne fait que s'asseoir et définir une sémantique significative. Je dirais que la sémantique d'une méthode statique dans une interface est remarquablement claire - même si le compilateur doit reporter la résolution de la méthode au moment de l'exécution.

Deuxièmement, le fait que nous utilisons des méthodes statiques signifie qu'il y a une raison valable d'avoir un modèle d'interface qui inclut des méthodes statiques - je ne peux parler pour vous, mais j'utilise régulièrement des méthodes statiques.

La réponse correcte la plus probable est qu'il n'y avait pas de besoin perçu, au moment où le langage a été défini, de méthodes statiques dans les interfaces. Java s'est beaucoup développé au fil des ans et c'est un élément qui a apparemment suscité un certain intérêt. Le fait qu'il ait été examiné pour Java 7 indique que son niveau a atteint un niveau d'intérêt pouvant entraîner un changement de langage. Pour ma part, je serai heureux quand je n'aurai plus à instancier un objet juste pour pouvoir appeler ma méthode getter non statique pour accéder à une variable statique dans une instance de sous-classe ...


5

Les méthodes statiques ne sont pas virtuelles comme les méthodes d'instance, donc je suppose que les concepteurs Java ont décidé qu'ils n'en voulaient pas dans les interfaces.

Mais vous pouvez mettre des classes contenant des méthodes statiques à l'intérieur des interfaces. Vous pouvez essayer ça!

public interface Test {
    static class Inner {
        public static Object get() {
            return 0;
        }
    }
}

5
  • "Y a-t-il une raison particulière pour laquelle les méthodes statiques ne peuvent pas être remplacées".

Permettez-moi de reformuler cette question pour vous en remplissant les définitions.

  • "Y a-t-il une raison particulière pour laquelle les méthodes résolues au moment de la compilation ne peuvent pas être résolues au moment de l'exécution."

Ou, pour mettre plus complètement, si je veux appeler une méthode sans instance, mais en connaissant la classe, comment puis-je la résoudre en fonction de l'instance que je n'ai pas.


3

Plusieurs réponses ont discuté des problèmes liés au concept de méthodes statiques remplaçables. Cependant, parfois, vous rencontrez un modèle où il semble que c'est exactement ce que vous souhaitez utiliser.

Par exemple, je travaille avec une couche relationnelle aux objets qui a des objets de valeur, mais aussi des commandes pour manipuler les objets de valeur. Pour diverses raisons, chaque classe d'objet valeur doit définir des méthodes statiques qui permettent au framework de trouver l'instance de commande. Par exemple, pour créer une personne que vous feriez:

cmd = createCmd(Person.getCreateCmdId());
Person p = cmd.execute();

et pour charger une personne par ID que vous feriez

cmd = createCmd(Person.getGetCmdId());
cmd.set(ID, id);
Person p = cmd.execute();

C'est assez pratique, mais cela a ses problèmes; notamment l'existence des méthodes statiques ne peut être imposée dans l'interface. Une méthode statique remplaçable dans l'interface serait exactement ce dont nous aurions besoin, si seulement cela pouvait fonctionner d'une manière ou d'une autre.

Les EJB résolvent ce problème en ayant une interface Home; chaque objet sait trouver sa maison et la maison contient les méthodes "statiques". De cette façon, les méthodes "statiques" peuvent être remplacées au besoin, et vous n'encombrez pas l'interface normale (elle s'appelle "Remote") avec des méthodes qui ne s'appliquent pas à une instance de votre bean. Faites juste que l'interface normale spécifie une méthode "getHome ()". Retourne une instance de l'objet Home (qui pourrait être un singleton, je suppose) et l'appelant peut effectuer des opérations qui affectent tous les objets Person.


3

Commentant EDIT: As of Java 8, static methods are now allowed in interfaces.

C'est juste, les méthodes statiques puisque Java 8 sont autorisées dans les interfaces, mais votre exemple ne fonctionnera toujours pas. Vous ne pouvez pas simplement définir une méthode statique: vous devez l'implémenter ou vous obtiendrez une erreur de compilation.


2

Eh bien, sans génériques, les interfaces statiques sont inutiles car tous les appels de méthode statique sont résolus au moment de la compilation. Il n'y a donc aucune utilité réelle pour eux.

Avec les génériques, ils ont une utilité - avec ou sans implémentation par défaut. De toute évidence, il faudrait qu'il y ait priorité et ainsi de suite. Cependant, je suppose que cette utilisation n'était pas très OO (comme le soulignent les autres réponses) et n'était donc pas considérée comme valant l'effort dont ils auraient besoin pour mettre en œuvre utilement.


1
Qu'est-ce que les génériques ont à voir avec ça? Une méthode statique sur une interface ne serait toujours pas exécutable.
DJClayworth

Ce serait d'abord une décision de mise en œuvre. Mais je suppose qu'il ne veut pas appeler des méthodes statiques sur une interface (il pourrait simplement utiliser une classe). Mais à la place, veut avoir quelque chose comme une classe de types ou autre chose sur les paramètres de type. En fait, son dernier montage le montre encore plus clairement.
MichaelGG

2
Why can't I define a static method in a Java interface?

Toutes les méthodes d'une interface sont explicitement abstraites et vous ne pouvez donc pas les définir comme statiques car les méthodes statiques ne peuvent pas être abstraites.


1

Une interface ne peut jamais être déréférencée statiquement, par exemple ISomething.member. Une interface est toujours déréférencée via une variable qui fait référence à une instance d'une sous-classe de l'interface. Ainsi, une référence d'interface ne peut jamais savoir à quelle sous-classe elle se réfère sans une instance de sa sous-classe.

Ainsi, l'approximation la plus proche d'une méthode statique dans une interface serait une méthode non statique qui ignore "ceci", c'est-à-dire qui n'accède à aucun membre non statique de l'instance. À l'abstraction de bas niveau, chaque méthode non statique (après recherche dans n'importe quelle table virtuelle) n'est vraiment qu'une fonction avec une portée de classe qui prend "ceci" comme paramètre formel implicite. Voyez l'objet singleton de Scala et l'interopérabilité avec Java comme preuve de ce concept. Et donc, chaque méthode statique est une fonction avec une portée de classe qui ne prend pas de paramètre "this". Ainsi, normalement, une méthode statique peut être appelée statiquement, mais comme indiqué précédemment, une interface n'a pas d'implémentation (est abstraite).

Ainsi, pour obtenir l'approximation la plus proche d'une méthode statique dans une interface, c'est utiliser une méthode non statique, puis n'accéder à aucun des membres d'instance non statiques. Il n'y aurait aucun autre avantage possible en termes de performances, car il n'existe aucun moyen de lier statiquement (au moment de la compilation) a ISomething.member(). Le seul avantage que je vois d'une méthode statique dans une interface est qu'elle n'entrerait pas (c'est-à-dire ignorerait) un "ceci" implicite et interdirait ainsi l'accès à l'un des membres d'instance non statiques. Cela signifierait implicitement que la fonction qui n'accède pas à "this" est immutée et même pas en lecture seule par rapport à sa classe contenante. Mais une déclaration de "statique" dans une interfaceISomething confondrait également les personnes qui ont essayé d'y accéder avecISomething.member()ce qui provoquerait une erreur de compilation. Je suppose que si l'erreur du compilateur était suffisamment explicative, ce serait mieux que d'essayer d'éduquer les gens sur l'utilisation d'une méthode non statique pour accomplir ce qu'ils veulent (principalement des méthodes d'usine), comme nous le faisons ici (et cela a été répété pendant 3 Q & A fois sur ce site), c'est donc évidemment un problème qui n'est pas intuitif pour beaucoup de gens. J'ai dû y réfléchir pendant un certain temps pour bien comprendre.

La façon d'obtenir un champ statique mutable dans une interface est d'utiliser des méthodes getter et setter non statiques dans une interface, pour accéder à ce champ statique dans la sous-classe. Sidenote, des statiques apparemment immuables peuvent être déclarées dans une interface Java avec static final.


0

Les interfaces fournissent simplement une liste de choses qu'une classe fournira, pas une implémentation réelle de ces choses, ce qui est votre élément statique.

Si vous voulez de la statique, utilisez une classe abstraite et héritez-la, sinon, supprimez la statique.

J'espère que cela pourra aider!


2
Eh bien, en théorie, vous pouvez définir une interface pour inclure un comportement statique, c'est-à-dire que "les implémentations de cette interface auront une méthode statique foo () avec cette signature", et laisser l'implémentation à la classe spécifique. J'ai rencontré des situations où ce comportement serait utile.
Rob

0

Vous ne pouvez pas définir de méthodes statiques dans une interface car les méthodes statiques appartiennent à une classe et non à une instance de classe, et les interfaces ne sont pas des classes. En savoir plus ici.

Cependant, si vous le souhaitez, vous pouvez le faire:

public class A {
  public static void methodX() {
  }
}

public class B extends A {
  public static void methodX() {
  }
}

Dans ce cas, vous avez deux classes avec 2 méthodes statiques distinctes appelées methodX ().


0

Supposons que vous puissiez le faire; considérez cet exemple:

interface Iface {
  public static void thisIsTheMethod();
}

class A implements Iface {

  public static void thisIsTheMethod(){
    system.out.print("I'm class A");
  }

}

class B extends Class A {

  public static void thisIsTheMethod(){
    System.out.print("I'm class B");
  } 
}

SomeClass {

  void doStuff(Iface face) {
    IFace.thisIsTheMethod();
    // now what would/could/should happen here.
  }

}

1
Il afficherait "Je suis de classe A". Cependant, si vous avez tapé, A.thisIsTheMethod()il afficherait "Je suis de classe B".
cdmckay

mais en appelant les méthodes sur l'interface, comment sauriez-vous (ou le compilateur) quelle méthode devrait être appelée? (rember il peut y avoir plus de classes implémentant Iface de façon drastique
pvgoddijn

désolé, je voulais dire: Cependant, si vous avez tapé B.thisIsTheMethod() cela afficherait "Je suis de classe B".
cdmckay

J'ai dit IFace.thisIsTHeMethod exprès car c'est là que réside le problème. il ne serait pas possible de l'appeler sur l'interface sans comportement indéfini (même si son déclaré dessus)
pvgoddijn

0

Quelque chose qui pourrait être implémenté est une interface statique (au lieu d'une méthode statique dans une interface). Toutes les classes implémentant une interface statique donnée doivent implémenter les méthodes statiques correspondantes. Vous pouvez obtenir une interface statique SI à partir de n'importe quelle classe

SI si = clazz.getStatic(SI.class); // null if clazz doesn't implement SI
// alternatively if the class is known at compile time
SI si = Someclass.static.SI; // either compiler errror or not null

alors vous pouvez appeler si.method(params). Cela serait utile (pour le modèle de conception d'usine par exemple) car vous pouvez obtenir (ou vérifier l'implémentation de) l'implémentation de méthodes statiques SI à partir d'une classe de compilation inconnue! Une répartition dynamique est nécessaire et vous pouvez remplacer les méthodes statiques (si elles ne sont pas définitives) d'une classe en l'étendant (lorsqu'elle est appelée via l'interface statique). De toute évidence, ces méthodes ne peuvent accéder qu'aux variables statiques de leur classe.


0

Alors que je me rends compte que Java 8 résout ce problème, je pensais que je ferais sienne un scénario sur lequel je travaille actuellement (verrouillé en utilisant Java 7) où il serait utile de pouvoir spécifier des méthodes statiques dans une interface.

J'ai plusieurs définitions d'énumération où j'ai défini des champs "id" et "displayName" ainsi que des méthodes d'assistance évaluant les valeurs pour diverses raisons. L'implémentation d'une interface me permet de m'assurer que les méthodes getter sont en place mais pas les méthodes d'assistance statiques. Étant une énumération, il n'y a vraiment pas de moyen propre de décharger les méthodes d'assistance dans une classe abstraite héritée ou quelque chose de similaire, de sorte que les méthodes doivent être définies dans l'énumération elle-même. Aussi parce que c'est une énumération, vous ne pourrez jamais le passer réellement comme un objet instancié et le traiter comme le type d'interface, mais être capable d'exiger l'existence des méthodes d'assistance statiques via une interface est ce que j'aime il est pris en charge dans Java 8.

Voici le code illustrant mon point.

Définition de l'interface:

public interface IGenericEnum <T extends Enum<T>> {
    String getId();
    String getDisplayName();
    //If I was using Java 8 static helper methods would go here
}

Exemple d'une définition d'énumération:

public enum ExecutionModeType implements IGenericEnum<ExecutionModeType> {
    STANDARD ("Standard", "Standard Mode"),
    DEBUG ("Debug", "Debug Mode");

    String id;
    String displayName;

    //Getter methods
    public String getId() {
        return id;
    }

    public String getDisplayName() {
        return displayName;
    }

    //Constructor
    private ExecutionModeType(String id, String displayName) {
        this.id = id;
        this.displayName = displayName;
    }

    //Helper methods - not enforced by Interface
    public static boolean isValidId(String id) {
        return GenericEnumUtility.isValidId(ExecutionModeType.class, id);
    }

    public static String printIdOptions(String delimiter){
        return GenericEnumUtility.printIdOptions(ExecutionModeType.class, delimiter);
    }

    public static String[] getIdArray(){
        return GenericEnumUtility.getIdArray(ExecutionModeType.class);
    }

    public static ExecutionModeType getById(String id) throws NoSuchObjectException {
        return GenericEnumUtility.getById(ExecutionModeType.class, id);
    }
}

Définition de l'utilitaire enum générique:

public class GenericEnumUtility {
    public static <T extends Enum<T> & IGenericEnum<T>> boolean isValidId(Class<T> enumType, String id) {       
        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            if(enumOption.getId().equals(id)) {
                return true;
            }
        }

        return false;
    }

    public static <T extends Enum<T> & IGenericEnum<T>> String printIdOptions(Class<T> enumType, String delimiter){
        String ret = "";
        delimiter = delimiter == null ? " " : delimiter;

        int i = 0;
        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            if(i == 0) {
                ret = enumOption.getId();
            } else {
                ret += delimiter + enumOption.getId();
            }           
            i++;
        }

        return ret;
    }

    public static <T extends Enum<T> & IGenericEnum<T>> String[] getIdArray(Class<T> enumType){
        List<String> idValues = new ArrayList<String>();

        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            idValues.add(enumOption.getId());
        }

        return idValues.toArray(new String[idValues.size()]);
    }

    @SuppressWarnings("unchecked")
    public static <T extends Enum<T> & IGenericEnum<T>> T getById(Class<T> enumType, String id) throws NoSuchObjectException {
        id = id == null ? "" : id;
        for(IGenericEnum<T> enumOption : enumType.getEnumConstants()) {
            if(id.equals(enumOption.getId())) {
                return (T)enumOption;
            }
        }

        throw new NoSuchObjectException(String.format("ERROR: \"%s\" is not a valid ID. Valid IDs are: %s.", id, printIdOptions(enumType, " , ")));
    }
}

0

Supposons que les méthodes statiques soient autorisées dans les interfaces: * Elles forceraient toutes les classes d'implémentation à déclarer cette méthode. * Les interfaces sont généralement utilisées via des objets, de sorte que les seules méthodes efficaces sur celles-ci sont celles non statiques. * Toute classe qui connaît une interface particulière pourrait invoquer ses méthodes statiques. Par conséquent, une méthode statique d'une classe d'implémentation serait appelée en dessous, mais la classe invocatrice ne sait pas laquelle. Comment le savoir? Il n'a aucune instanciation pour le deviner!

On pensait que les interfaces étaient utilisées pour travailler avec des objets. De cette façon, un objet est instancié à partir d'une classe particulière, donc ce dernier problème est résolu. La classe invoquante n'a pas besoin de savoir quelle classe particulière est parce que l'instanciation peut être effectuée par une troisième classe. Ainsi, la classe invoquante ne connaît que l'interface.

Si nous voulons que cela soit étendu aux méthodes statiques, nous devrions avoir la possibilité de spécifier une classe d'implémentation avant, puis de passer une référence à la classe invoquante. Cela pourrait utiliser la classe via les méthodes statiques de l'interface. Mais quelle est la différence entre cette référence et un objet? Nous avons juste besoin d'un objet représentant ce que c'était la classe. Désormais, l'objet représente l'ancienne classe et pourrait implémenter une nouvelle interface incluant les anciennes méthodes statiques - celles-ci sont désormais non statiques.

Les métaclasses servent à cet effet. Vous pouvez essayer la classe Class of Java. Mais le problème est que Java n'est pas assez flexible pour cela. Vous ne pouvez pas déclarer une méthode dans l'objet classe d'une interface.

Ceci est un problème de méta - quand vous devez faire du cul

..blah blah

de toute façon, vous avez une solution simple: rendre la méthode non statique avec la même logique. Mais ensuite, vous devez d'abord créer un objet pour appeler la méthode.


0

Pour résoudre ce problème: erreur: corps de la méthode manquant ou déclaration abstraite statique void main (String [] args);

interface I
{
    int x=20;
    void getValue();
    static void main(String[] args){};//Put curly braces 
}
class InterDemo implements I
{
    public void getValue()
    {
    System.out.println(x);
    }
    public static void main(String[] args)
    {
    InterDemo i=new InterDemo();
    i.getValue();   
    }

}

sortie: 20

Maintenant, nous pouvons utiliser une méthode statique dans l'interface


1
C'est inutile, cependant. La définition d'une méthode statique sur une interface n'applique pas d'autres définitions dans les classes qui implémentent une telle interface. Si vous supprimez simplement la méthode statique de l'interface I, votre code se compilera et s'exécutera de toute façon sans problème. En d'autres termes, vous ne remplacez PAS la méthode principale de l'interface I dans la classe InterDemo, vous créez simplement une nouvelle méthode avec la même signature.
Fran Marzoa

-2

Je pense que java n'a pas de méthodes d'interface statiques car vous n'en avez pas besoin. Vous pensez peut-être que oui, mais ... Comment les utiliseriez-vous? Si vous voulez les appeler comme

MyImplClass.myMethod()

alors vous n'avez pas besoin de le déclarer dans l'interface. Si vous voulez les appeler comme

myInstance.myMethod()

alors il ne devrait pas être statique. Si vous allez réellement utiliser la première manière, mais que vous souhaitez simplement imposer à chaque implémentation d'avoir une telle méthode statique, alors c'est vraiment une convention de codage, pas un contrat entre l'instance qui implémente une interface et le code appelant.

Les interfaces vous permettent de définir le contrat entre l'instance de classe qui implémente l'interface et le code appelant. Et java vous aide à être sûr que ce contrat n'est pas violé, vous pouvez donc vous y fier et ne vous inquiétez pas quelle classe met en œuvre ce contrat, juste "quelqu'un qui a signé un contrat" ​​suffit. En cas d'interfaces statiques votre code

MyImplClass.myMethod()

ne repose pas sur le fait que chaque implémentation d'interface possède cette méthode, vous n'avez donc pas besoin de java pour vous aider à en être sûr.


-5

Quel est le besoin d'une méthode statique dans l'interface, les méthodes statiques sont utilisées essentiellement lorsque vous n'avez pas à créer une instance d'objet.L'idée d'interface est d'apporter des concepts POO avec l'introduction de la méthode statique que vous détournez du concept.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.