La question est en Java pourquoi je ne peux pas définir une méthode statique abstraite? par exemple
abstract class foo {
abstract void bar( ); // <-- this is ok
abstract static void bar2(); //<-- this isn't why?
}
Parce que "abstrait" signifie: "N'implémente aucune fonctionnalité" et "statique" signifie: "Il y a une fonctionnalité même si vous n'avez pas d'instance d'objet". Et c'est une contradiction logique.
Mauvaise conception de la langue. Il serait beaucoup plus efficace d'appeler directement une méthode abstraite statique que de créer une instance uniquement pour utiliser cette méthode abstraite. Cela est particulièrement vrai lorsqu’on utilise une classe abstraite comme solution de contournement en cas d’impossibilité d’extension, qui est un autre exemple de conception médiocre. J'espère qu'ils résoudront ces limitations dans une prochaine version.
Vous ne pouvez pas écraser une méthode statique, le rendre abstrait n'aura donc aucun sens. De plus, une méthode statique dans une classe abstraite appartiendrait à cette classe, et non à la classe de substitution, elle ne pourrait donc pas être utilisée.
L'annotation abstract
à une méthode indique que celle-ci DOIT être remplacée dans une sous-classe.
En Java, un membre static
(méthode ou champ) ne peut pas être remplacé par des sous-classes (ceci n'est pas nécessairement vrai dans d'autres langages orientés objet, voir Smalltalk.) Un membre static
peut être hidden , mais il est fondamentalement différent de écrasé .
Comme les membres statiques ne peuvent pas être remplacés dans une sous-classe, l'annotation abstract
ne peut pas leur être appliquée.
En passant, d'autres langages supportent l'héritage statique, tout comme l'héritage d'instance. Du point de vue de la syntaxe, ces langues exigent généralement que le nom de la classe soit inclus dans l'instruction. Par exemple, en Java, en supposant que vous écriviez du code dans ClassA, il s'agit d'instructions équivalentes (si methodA () est une méthode statique et qu'il n'existe aucune méthode d'instance avec la même signature):
ClassA.methodA();
et
methodA();
Dans Smalltalk, le nom de la classe n’est pas facultatif. Par conséquent, la syntaxe est la suivante (notez que Smalltalk n’utilise pas le.. Pour séparer le "sujet" et le "verbe", mais l’utilise plutôt comme terminateur de statemend):
ClassA methodA.
Comme le nom de classe est toujours requis, la "version" correcte de la méthode peut toujours être déterminée en parcourant la hiérarchie des classes. Pour ce que cela vaut, je manque parfois l'héritage static
, et j'ai été piqué par le manque d'héritage statique en Java lorsque j'ai commencé à l'utiliser. De plus, Smalltalk est typé «canard» (et ne prend donc pas en charge programme par contrat.) Ainsi, il n'a pas de modificateur abstract
pour les membres de la classe.
J'ai aussi posé la même question, voici pourquoi
Depuis la classe abstraite dit, il ne donnera pas la mise en œuvre et permettre à la sous-classe de le donner
donc Subclass doit remplacer les méthodes de Superclass,
RÈGLE NO 1 - Une méthode statique ne peut pas être remplacée
Étant donné que les membres et les méthodes statiques sont des éléments de compilation, c'est pourquoi la surcharge (polymorphisme de la compilation) des méthodes statiques est autorisée plutôt que la substitution (polymorphisme d'exécution)
Donc, ils ne peuvent pas être abstraits.
Il n'y a rien qui ressemble à abstract static <--- Non autorisé dans Java Universe
C'est une conception de langage terrible et vraiment aucune raison pour laquelle cela ne peut pas être possible.
En fait, voici une implémentation sur la façon dont PEUT être fait dans Java:
public class Main {
public static void main(String[] args) {
// This is done once in your application, usually at startup
Request.setRequest(new RequestImplementationOther());
Request.doSomething();
}
public static final class RequestImplementationDefault extends Request {
@Override
void doSomethingImpl() {
System.out.println("I am doing something AAAAAA");
}
}
public static final class RequestImplementaionOther extends Request {
@Override
void doSomethingImpl() {
System.out.println("I am doing something BBBBBB");
}
}
// Static methods in here can be overriden
public static abstract class Request {
abstract void doSomethingImpl();
// Static method
public static void doSomething() {
getRequest().doSomethingImpl();
}
private static Request request;
private static Request getRequest() {
// If setRequest is never called prior, it will default to a default implementation. Of course you could ignore that too.
if ( request == null ) {
return request = new RequestImplementationDefault();
}
return request;
}
public static Request setRequest(Request r){
return request = r;
}
}
}
================= Ancien exemple ci-dessous =================
Recherchez getRequest et getRequestImpl ... setInstance peut être appelé pour modifier l'implémentation avant l'appel.
import Java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* @author Mo. Joseph
* @date 16 mar 2012
**/
public abstract class Core {
// ---------------------------------------------------------------
private static Core singleton;
private static Core getInstance() {
if ( singleton == null )
setInstance( new Core.CoreDefaultImpl() ); // See bottom for CoreDefaultImpl
return singleton;
}
public static void setInstance(Core core) {
Core.singleton = core;
}
// ---------------------------------------------------------------
// Static public method
public static HttpServletRequest getRequest() {
return getInstance().getRequestImpl();
}
// A new implementation would override this one and call setInstance above with that implementation instance
protected abstract HttpServletRequest getRequestImpl();
// ============================ CLASSES =================================
// ======================================================================
// == Two example implementations, to alter getRequest() call behaviour
// == getInstance() have to be called in all static methods for this to work
// == static method getRequest is altered through implementation of getRequestImpl
// ======================================================================
/** Static inner class CoreDefaultImpl */
public static class CoreDefaultImpl extends Core {
protected HttpServletRequest getRequestImpl() {
return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
}
}
/** Static inner class CoreTestImpl : Alternative implementation */
public static class CoreTestImpl extends Core {
protected HttpServletRequest getRequestImpl() {
return new MockedRequest();
}
}
}
Une méthode abstraite est définie uniquement pour pouvoir être remplacée dans une sous-classe. Cependant, les méthodes statiques ne peuvent pas être remplacées. Par conséquent, le fait d'avoir une méthode abstraite et statique est une erreur de compilation.
Maintenant la question suivante est pourquoi les méthodes statiques ne peuvent pas être remplacées?
C'est parce que les méthodes statiques appartiennent à une classe particulière et non à son instance. Si vous essayez de remplacer une méthode statique, vous ne recevrez aucune erreur de compilation ou d'exécution, mais le compilateur cacherait simplement la méthode statique de la superclasse.
Je vois qu'il y a déjà un dieu-zillion de réponses mais je ne vois pas de solutions pratiques. Bien sûr, il s’agit d’un problème réel et il n’existe aucune raison valable d’exclure cette syntaxe en Java. Puisque la question initiale manque d'un contexte où cela peut être nécessaire, je fournis à la fois un contexte et une solution:
Supposons que vous ayez une méthode statique dans un groupe de classes identiques. Ces méthodes appellent une méthode statique spécifique à la classe:
class C1 {
static void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
private static void doMoreWork(int k) {
// code specific to class C1
}
}
class C2 {
static void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
private static void doMoreWork(int k) {
// code specific to class C2
}
}
Les méthodes doWork()
dans C1
et C2
sont identiques. Il peut y avoir beaucoup de ces calculs: C3
C4
etc. Si static abstract
était autorisé, vous élimineriez le code dupliqué en procédant comme suit:
abstract class C {
static void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
static abstract void doMoreWork(int k);
}
class C1 extends C {
private static void doMoreWork(int k) {
// code for class C1
}
}
class C2 extends C {
private static void doMoreWork(int k) {
// code for class C2
}
}
mais cela ne compilerait pas car la combinaison static abstract
n'est pas autorisée . Cependant, ceci peut être contourné avec la construction static class
, qui est autorisée:
abstract class C {
void doWork() {
...
for (int k: list)
doMoreWork(k);
...
}
abstract void doMoreWork(int k);
}
class C1 {
private static final C c = new C(){
@Override void doMoreWork(int k) {
System.out.println("code for C1");
}
};
public static void doWork() {
c.doWork();
}
}
class C2 {
private static final C c = new C() {
@Override void doMoreWork(int k) {
System.out.println("code for C2");
}
};
public static void doWork() {
c.doWork();
}
}
Avec cette solution, le seul code dupliqué est
public static void doWork() {
c.doWork();
}
Une classe abstraite ne peut pas avoir de méthode statique car une abstraction est effectuée pour obtenir une LIAISON DYNAMIQUE alors que les méthodes statiques sont liées de manière statique à leur fonctionnalité. Une méthode statique signifie que le comportement de required.Just the class.Static Les méthodes appartiennent à la classe et non à l'objet . Elles sont stockées dans une zone mémoire appelée PERMGEN à partir de laquelle il est partagé avec chaque objet . Les méthodes de la classe abstraite sont dynamiquement liées à leurs fonctionnalités. .
Supposons qu'il existe deux classes, Parent
et Child
. Parent
est abstract
. Les déclarations sont les suivantes:
abstract class Parent {
abstract void run();
}
class Child extends Parent {
void run() {}
}
Cela signifie que toute instance de Parent
doit spécifier comment run()
est exécuté.
Cependant, supposons maintenant que Parent
ne soit pas abstract
.
class Parent {
static void run() {}
}
Cela signifie que Parent.run()
exécutera la méthode statique.
La définition d'une méthode abstract
est "Une méthode déclarée mais non implémentée", ce qui signifie qu'elle ne renvoie rien elle-même.
La définition d'une méthode static
est "Une méthode qui renvoie la même valeur pour les mêmes paramètres, quelle que soit l'instance sur laquelle elle est appelée".
La valeur de retour d'une méthode abstract
changera à mesure que l'instance change. Une méthode static
ne le fera pas. Une méthode static abstract
est à peu près une méthode où la valeur de retour est constante, mais ne renvoie rien. C'est une contradiction logique.
En outre, il n'y a vraiment pas beaucoup de raisons pour une méthode static abstract
.
Une méthode statique, par définition, n'a pas besoin de connaître this
. Ainsi, il ne peut pas s'agir d'une méthode virtuelle (surchargée en fonction des informations de sous-classes dynamiques disponibles via this
); à la place, une surcharge de méthode statique est uniquement basée sur les informations disponibles au moment de la compilation (cela signifie: une fois que vous vous référez à une méthode statique de superclasse, vous appelez notamment la méthode superclass, mais jamais une méthode de sous-classe).
Selon cela, les méthodes statiques abstraites seraient totalement inutiles, car leur référence ne sera jamais remplacée par un corps défini.
Une méthode statique peut être appelée sans instance de la classe. Dans votre exemple, vous pouvez appeler foo.bar2 (), mais pas foo.bar (), car pour bar vous avez besoin d'une instance .
foo var = new ImplementsFoo();
var.bar();
Si vous appelez une méthode statique, elle sera toujours exécutée avec le même code. Dans l'exemple ci-dessus, même si vous redéfinissez bar2 dans ImplementsFoo, un appel à var.bar2 () exécuterait foo.bar2 ().
Si bar2 n'a plus d'implémentation (c'est ce que signifie abstrait), vous pouvez appeler une méthode sans implémentation. C'est très nocif.
Parce que la classe abstraite est un concept OOPS et que les membres statiques ne font pas partie d'OOPS ....
Nous pouvons maintenant déclarer des méthodes complètes statiques dans une interface et exécuter une interface en déclarant la méthode principale dans une interface.
interface Demo
{
public static void main(String [] args) {
System.out.println("I am from interface");
}
}
Je pense avoir trouvé la réponse à cette question, en expliquant pourquoi les méthodes d'une interface (qui fonctionnent comme des méthodes abstraites dans une classe parente) ne peuvent pas être statiques. Voici la réponse complète (pas la mienne)
En principe, les méthodes statiques peuvent être liées à la compilation, car pour les appeler, vous devez spécifier une classe. Cela diffère des méthodes d'instance, pour lesquelles la classe de la référence à partir de laquelle vous appelez la méthode peut être inconnue au moment de la compilation (ainsi, le bloc de code appelé ne peut être déterminé qu'au moment de l'exécution).
Si vous appelez une méthode statique, vous connaissez déjà la classe dans laquelle elle est implémentée, ou l'une de ses sous-classes directes. Si vous définissez
abstract class Foo {
abstract static void bar();
}
class Foo2 {
@Override
static void bar() {}
}
Alors, tout appel à Foo.bar();
est évidemment illégal et vous utiliserez toujours Foo2.bar();
.
Dans cet esprit, le seul but d'une méthode abstraite statique serait de forcer les sous-classes à implémenter une telle méthode. Vous pensez peut-être au début que cela est TRÈS faux, mais si vous avez un paramètre de type générique <E extends MySuperClass>
, il serait agréable de garantir via l'interface que E
peut .doSomething()
. N'oubliez pas qu'en raison de l'effacement des types, les génériques n'existent qu'au moment de la compilation.
Alors, serait-ce utile? Oui, et c'est peut-être pour cette raison que Java 8 autorise les méthodes statiques dans les interfaces (bien qu'avec une implémentation par défaut). Pourquoi pas des méthodes statiques abstraites avec une implémentation par défaut dans les classes? Tout simplement parce qu'une méthode abstraite avec une implémentation par défaut est en réalité une méthode concrète.
Pourquoi pas des méthodes abstraites/interfaces statiques sans implémentation par défaut? Apparemment, simplement à cause de la manière dont Java identifie le bloc de code qu'il doit exécuter (première partie de ma réponse).
L'idée d'avoir une méthode statique abstraite serait que vous ne pouvez pas utiliser cette classe abstraite particulière directement pour cette méthode, mais seule la première dérivée serait autorisée à implémenter cette méthode statique (ou pour les génériques: utilisation).
De cette façon, vous pouvez créer par exemple une classe abstraite sortableObject ou même une interface Avec des méthodes statiques (auto-) abstraites, qui définissent les paramètres des options de tri:
public interface SortableObject {
public [abstract] static String [] getSortableTypes();
public String getSortableValueByType(String type);
}
Vous pouvez maintenant définir un objet triable qui peut être trié selon les types principaux identiques pour tous ces objets:
public class MyDataObject implements SortableObject {
final static String [] SORT_TYPES = {
"Name","Date of Birth"
}
static long newDataIndex = 0L ;
String fullName ;
String sortableDate ;
long dataIndex = -1L ;
public MyDataObject(String name, int year, int month, int day) {
if(name == null || name.length() == 0) throw new IllegalArgumentException("Null/empty name not allowed.");
if(!validateDate(year,month,day)) throw new IllegalArgumentException("Date parameters do not compose a legal date.");
this.fullName = name ;
this.sortableDate = MyUtils.createSortableDate(year,month,day);
this.dataIndex = MyDataObject.newDataIndex++ ;
}
public String toString() {
return ""+this.dataIndex+". "this.fullName+" ("+this.sortableDate+")";
}
// override SortableObject
public static String [] getSortableTypes() { return SORT_TYPES ; }
public String getSortableValueByType(String type) {
int index = MyUtils.getStringArrayIndex(SORT_TYPES, type);
switch(index) {
case 0: return this.name ;
case 1: return this.sortableDate ;
}
return toString(); // in the order they were created when compared
}
}
Maintenant, vous pouvez créer un
public class SortableList<T extends SortableObject>
qui peut récupérer les types, créer un menu contextuel pour sélectionner un type sur lequel trier et utiliser la liste en extrayant les données de ce type, ainsi qu'une fonction d'ajout qui, lorsqu'un type de tri est sélectionné, peut -sort de nouveaux éléments dans . Notez que l'instance de SortableList peut accéder directement à la méthode statique de "T":
String [] MenuItems = T.getSortableTypes();
Le problème de devoir utiliser une instance est que SortableList n'a peut-être pas encore d'éléments, mais doit déjà fournir le tri préféré.
Cheerio, Olaf.
Premièrement, un point clé concernant les classes abstraites - Une classe abstraite ne peut pas être instanciée (voir wiki ). Vous ne pouvez donc pas créer aucune instance d'une classe abstraite.
Maintenant, Java traite les méthodes statiques en partageant la méthode avec tous les instances de cette classe.
Donc, si vous ne pouvez pas instancier une classe, cette classe ne peut pas avoir de méthodes abstraites statiques, car une méthode abstraite demande à être étendue.
Boom.
Parce que abstract est un mot-clé qui s'applique aux méthodes abstraites ne spécifie pas de corps Et si nous parlons de mot clé statique, il appartient à la classe.
Parce que 'abstrait' signifie que la méthode doit être remplacée et qu'il est impossible de remplacer les méthodes 'statiques'.
Selon Java doc :
Une méthode statique est une méthode associée à la classe dans laquelle il est défini plutôt qu'avec n'importe quel objet. Chaque instance de la classe partage ses méthodes statiques
En Java 8, avec les méthodes par défaut, les méthodes statiques sont également autorisées dans une interface. Cela nous permet d’organiser plus facilement des méthodes d’aide dans nos bibliothèques. Nous pouvons garder les méthodes statiques spécifiques à une interface dans la même interface plutôt que dans une classe séparée.
Un bel exemple de ceci est:
list.sort(ordering);
au lieu de
Collections.sort(list, ordering);
Un autre exemple d'utilisation de méthodes statiques est également donné dans 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));
}
}
Les méthodes classiques peuvent être abstraites lorsqu'elles sont censées être remplacées par des sous-classes et dotées de fonctionnalités. Imaginez que la classe Foo
soit étendue de Bar1, Bar2, Bar3
etc. Ainsi, chacun aura sa propre version de la classe abstraite en fonction de ses besoins.
Maintenant, les méthodes statiques appartiennent par définition à la classe, elles n’ont rien à voir avec les objets de la classe ou les objets de ses sous-classes. Ils n'ont même pas besoin d'eux pour exister, ils peuvent être utilisés sans instancier les classes. Par conséquent, ils doivent être prêts à l'emploi et ne peuvent pas dépendre des sous-classes pour leur ajouter des fonctionnalités.
Vous pouvez le faire avec des interfaces en Java 8.
Voici la documentation officielle à ce sujet:
https://docs.Oracle.com/javase/tutorial/Java/IandI/defaultmethods.html
car si vous utilisez un membre statique ou une variable statique dans la classe, il se chargera au moment du chargement de la classe.
Déclarer une méthode en tant que static
signifie que nous pouvons appeler cette méthode par son nom de classe. Si cette classe est également abstract
, cela n’a aucun sens de l’appeler car elle ne contient aucun corps et nous ne pouvons donc pas déclarer une méthode à la fois en tant que static
et abstract
.