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:
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).
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?
la source
Réponses:
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:
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 un
NoSuchMethodError
.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?Comme vous devez nommer explicitement le type concret
Foo
lors 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 unIXMLizable
qui 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.
la source
RESET()
une classe donnée? Vous écririezSomeClass.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.T
sans savoirT
statiquement, 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.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:
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.
la source
static
c'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}.Normalement, cela se fait en utilisant un modèle d'usine
la source
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:
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.
la source
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.
la source
En fait, vous pouvez en Java 8.
Selon le document Java :
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:
au lieu de
Exemple de méthode statique (du doc lui-même):
la source
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.
la source
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 ...
la source
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!
la source
Permettez-moi de reformuler cette question pour vous en remplissant les définitions.
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.
la source
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:
et pour charger une personne par ID que vous feriez
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.
la source
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.
la source
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.
la source
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.
la source
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
.la source
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!
la source
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:
Dans ce cas, vous avez deux classes avec 2 méthodes statiques distinctes appelées methodX ().
la source
Supposons que vous puissiez le faire; considérez cet exemple:
la source
A.thisIsTheMethod()
il afficherait "Je suis de classe B".B.thisIsTheMethod()
cela afficherait "Je suis de classe B".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
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.la source
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:
Exemple d'une définition d'énumération:
Définition de l'utilitaire enum générique:
la source
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.
la source
Pour résoudre ce problème: erreur: corps de la méthode manquant ou déclaration abstraite statique void main (String [] args);
sortie: 20
Maintenant, nous pouvons utiliser une méthode statique dans l'interface
la source
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
alors vous n'avez pas besoin de le déclarer dans l'interface. Si vous voulez les appeler comme
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
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.
la source
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.
la source