Die Frage ist in Java, warum ich keine abstrakte statische Methode definieren kann. zum Beispiel
abstract class foo {
abstract void bar( ); // <-- this is ok
abstract static void bar2(); //<-- this isn't why?
}
Die Frage ist in Java, warum ich keine abstrakte statische Methode definieren kann. zum Beispiel
abstract class foo {
abstract void bar( ); // <-- this is ok
abstract static void bar2(); //<-- this isn't why?
}
Antworten:
Denn "abstrakt" bedeutet: "Implementiert keine Funktionalität" und "statisch" bedeutet: "Es gibt Funktionalität, auch wenn Sie keine Objektinstanz haben". Und das ist ein logischer Widerspruch.
abstract static
wäre, wäre das vollkommen sinnvoll. Es wäre eine Methode des Klassenobjekts selbst, die Unterklassenobjekte implementieren müssen. Natürlich ist die Art und Weise, wie Ihre Antwort steht, richtig, obwohl ich mich mit der Sprache befasst habe.
abstract static
: Eine Funktion X, die "in der Unterklasse implementiert" ist, kann nicht gleichzeitig "in der Klasse ausgeführt" werden - nur in der Unterklasse . Wo es dann nicht mehr abstrakt ist.
static
bedeutet nicht "nicht leer" - das ist nur eine Folge von Java, das nicht zulässt, dass statische Methoden abstrakt sind. Es bedeutet "aufrufbar für die Klasse". (Es sollte " nur für die Klasse aufrufbar" bedeuten, aber das ist ein anderes Problem.) Wenn Java abstract static
Methoden unterstützt , würde ich erwarten, dass die Methode 1) von Unterklassen implementiert werden muss und 2) eine Klassenmethode der Unterklasse ist. Einige Methoden sind als Instanzmethoden einfach nicht sinnvoll. Leider können Sie dies in Java beim Erstellen einer abstrakten Basisklasse (oder einer Schnittstelle) nicht angeben.
Schlechtes Sprachdesign. Es wäre viel effektiver, eine statische abstrakte Methode direkt aufzurufen, als eine Instanz nur für die Verwendung dieser abstrakten Methode zu erstellen. Dies gilt insbesondere dann, wenn eine abstrakte Klasse als Problemumgehung für die Enum-Unfähigkeit zum Erweitern verwendet wird. Dies ist ein weiteres schlechtes Designbeispiel. Ich hoffe, sie lösen diese Einschränkungen in einer nächsten Version.
static
selbst bereits eine Verletzung ist ....
Sie können eine statische Methode nicht überschreiben, daher wäre es bedeutungslos, sie abstrakt zu machen. Darüber hinaus würde eine statische Methode in einer abstrakten Klasse zu dieser Klasse gehören und nicht zur übergeordneten Klasse, sodass sie ohnehin nicht verwendet werden kann.
Die abstract
Anmerkung zu einer Methode gibt an, dass die Methode in einer Unterklasse überschrieben werden muss.
In Java kann ein static
Mitglied (Methode oder Feld) nicht durch Unterklassen überschrieben werden (dies gilt nicht unbedingt für andere objektorientierte Sprachen, siehe SmallTalk). Ein static
Mitglied kann ausgeblendet sein , dies unterscheidet sich jedoch grundlegend von dem überschriebenen .
Da statische Elemente in einer Unterklasse nicht überschrieben werden können, kann die abstract
Anmerkung nicht auf sie angewendet werden.
Abgesehen davon unterstützen andere Sprachen die statische Vererbung, genau wie die Instanzvererbung. Aus syntaktischer Sicht erfordern diese Sprachen normalerweise, dass der Klassenname in der Anweisung enthalten ist. In Java sind dies beispielsweise unter der Annahme, dass Sie Code in ClassA schreiben, äquivalente Anweisungen (wenn methodA () eine statische Methode ist und es keine Instanzmethode mit derselben Signatur gibt):
ClassA.methodA();
und
methodA();
In SmallTalk ist der Klassenname nicht optional, daher lautet die Syntax (beachten Sie, dass SmallTalk das. Nicht verwendet, um das "Subjekt" und das "Verb" zu trennen, sondern es stattdessen als Abschlusszeichen für statemend verwendet):
ClassA methodA.
Da der Klassenname immer erforderlich ist, kann die richtige "Version" der Methode immer durch Durchlaufen der Klassenhierarchie ermittelt werden. Für das, was es wert ist, vermisse ich gelegentlich die static
Vererbung und wurde von dem Mangel an statischer Vererbung in Java gebissen, als ich damit anfing. Darüber hinaus ist SmallTalk vom Typ Ente (und unterstützt daher kein vertragliches Programm). Daher gibt es keinen abstract
Modifikator für Klassenmitglieder.
Ich habe auch die gleiche Frage gestellt, hier ist warum
Da die Abstract-Klasse sagt, wird sie keine Implementierung geben und es der Unterklasse erlauben, sie zu geben
Die Unterklasse muss also die Methoden der Oberklasse überschreiben.
REGEL NR. 1 - Eine statische Methode kann nicht überschrieben werden
Da statische Elemente und Methoden Elemente zur Kompilierungszeit sind, ist das Überladen (Polymorphismus der Kompilierungszeit) statischer Methoden eher zulässig als das Überschreiben (Laufzeitpolymorphismus).
Sie können also nicht abstrakt sein.
Es gibt nichts wie abstrakte statische <--- In Java Universe nicht erlaubt
abstract static
siehe stackoverflow.com/questions/370962/... . Der wahre Grund, warum Java das Überschreiben statischer Methoden nicht zulässt, liegt darin, dass Java das Überschreiben statischer Methoden nicht zulässt.
foo(String)
ist es nicht dasselbe wie foo(Integer)
- das ist alles was es ist.
Dies ist ein schreckliches Sprachdesign und wirklich kein Grund, warum es nicht möglich sein kann.
In der Tat, hier ist eine Implementierung, wie es CAN in getan werden , 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;
}
}
}
================= Altes Beispiel unten =================
Suchen Sie nach getRequest, und getRequestImpl ... setInstance kann aufgerufen werden, um die Implementierung zu ändern, bevor der Aufruf erfolgt.
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();
}
}
}
Wird wie folgt verwendet:
static {
Core.setSingleton(new Core.CoreDefaultImpl());
// Or
Core.setSingleton(new Core.CoreTestImpl());
// Later in the application you might use
Core.getRequest();
}
abstract static
Methode angegeben haben, wie sie in der Frage gestellt wurde, und Sie haben in Fettdruck geschrieben, KANN IN JAVA GEMACHT WERDEN . Das ist völlig falsch.
Eine abstrakte Methode ist nur so definiert, dass sie in einer Unterklasse überschrieben werden kann. Statische Methoden können jedoch nicht überschrieben werden. Daher ist es ein Fehler bei der Kompilierung, eine abstrakte, statische Methode zu haben.
Nun ist die nächste Frage, warum statische Methoden nicht überschrieben werden können?
Dies liegt daran, dass statische Methoden zu einer bestimmten Klasse und nicht zu ihrer Instanz gehören. Wenn Sie versuchen, eine statische Methode zu überschreiben, wird kein Kompilierungs- oder Laufzeitfehler angezeigt, aber der Compiler würde nur die statische Methode der Oberklasse ausblenden.
Eine statische Methode muss per Definition nicht wissen this
. Daher kann es sich nicht um eine virtuelle Methode handeln (die gemäß den über verfügbaren dynamischen Unterklasseninformationen überladen ist this
). Stattdessen basiert eine statische Methodenüberladung ausschließlich auf Informationen, die zum Zeitpunkt der Kompilierung verfügbar sind (dies bedeutet: Wenn Sie eine statische Methode der Oberklasse referenzieren, rufen Sie nämlich die Oberklassenmethode auf, jedoch niemals eine Unterklassenmethode).
Demnach wären abstrakte statische Methoden völlig nutzlos, da die Referenz niemals durch einen definierten Körper ersetzt wird.
Ich sehe, dass es bereits unzählige Antworten gibt, aber ich sehe keine praktischen Lösungen. Dies ist natürlich ein echtes Problem und es gibt keinen guten Grund, diese Syntax in Java auszuschließen. Da der ursprünglichen Frage ein Kontext fehlt, in dem dies erforderlich sein könnte, biete ich sowohl einen Kontext als auch eine Lösung an:
Angenommen, Sie haben eine statische Methode in einer Reihe von Klassen, die identisch sind. Diese Methoden rufen eine statische Methode auf, die klassenspezifisch ist:
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
}
}
doWork()
Methoden in C1
und C2
sind identisch. Möglicherweise gibt es viele dieser Probleme: C3
C4
usw. Wenn dies static abstract
zulässig wäre, würden Sie den doppelten Code entfernen , indem Sie Folgendes tun:
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
}
}
Dies würde jedoch nicht kompiliert, da eine static abstract
Kombination nicht zulässig ist. Dies kann jedoch mit einem static class
Konstrukt umgangen werden , das erlaubt ist:
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();
}
}
Mit dieser Lösung wird nur Code dupliziert
public static void doWork() {
c.doWork();
}
C1.doWork()
oder C2.doWork()
Sie können jedoch nicht anrufen C.doWork()
. Nehmen wir auch in dem von Ihnen bereitgestellten Beispiel an, was nicht funktioniert. Angenommen, wenn dies zulässig war, wie findet die Klasse dann C
die Implementierung von doMoreWork()
? Schließlich würde ich Ihren Kontextcode als schlechtes Design bezeichnen. Warum? einfach, weil Sie eine separate Funktion für den Code erstellt haben, die eindeutig ist, anstatt eine Funktion für den gemeinsamen Code zu erstellen und dann eine statische Funktion in der Klasse zu implementieren C
. Das ist einfacher !!!
Angenommen, es gibt zwei Klassen Parent
und Child
. Parent
ist abstract
. Die Erklärungen lauten wie folgt:
abstract class Parent {
abstract void run();
}
class Child extends Parent {
void run() {}
}
Dies bedeutet, dass jede Instanz von Parent
angeben muss, wie sie run()
ausgeführt wird.
Nehmen wir jetzt jedoch an, dass dies Parent
nicht der Fall ist abstract
.
class Parent {
static void run() {}
}
Dies bedeutet, Parent.run()
dass die statische Methode ausgeführt wird.
Die Definition einer abstract
Methode lautet "Eine Methode, die deklariert, aber nicht implementiert ist", was bedeutet, dass sie selbst nichts zurückgibt.
Die Definition einer static
Methode lautet "Eine Methode, die unabhängig von der Instanz, auf der sie aufgerufen wird, denselben Wert für dieselben Parameter zurückgibt".
abstract
Der Rückgabewert einer Methode ändert sich, wenn sich die Instanz ändert. Eine static
Methode wird nicht. Eine static abstract
Methode ist so ziemlich eine Methode, bei der der Rückgabewert konstant ist, aber nichts zurückgibt. Dies ist ein logischer Widerspruch.
Es gibt auch wirklich keinen Grund für eine static abstract
Methode.
Eine abstrakte Klasse kann keine statische Methode haben, da eine Abstraktion durchgeführt wird, um eine DYNAMISCHE BINDUNG zu erreichen, während statische Methoden statisch an ihre Funktionalität gebunden sind. Eine statische Methode bedeutet, dass das Verhalten nicht von einer Instanzvariablen abhängig ist, sodass keine Instanz / kein Objekt erforderlich ist. Nur die Klasse. Statische Methoden gehören zur Klasse und nicht zum Objekt. Sie werden in einem als PERMGEN bekannten Speicherbereich gespeichert, von wo aus sie mit jedem Objekt gemeinsam genutzt werden. Methoden in abstrakten Klassen werden dynamisch an ihre Funktionalität gebunden.
Deklarieren eine Methode als static
Mittel , die wir diese Methode von seinen Klassennamen aufrufen können und wenn diese Klasse ist abstract
auch, macht es keinen Sinn , es zu nennen , da es keinen Körper enthält, und daher können wir keine Methode deklarieren sowohl als static
und abstract
.
Da abstrakte Methoden zur Klasse gehören und von der implementierenden Klasse nicht überschrieben werden können. Auch wenn es eine statische Methode mit derselben Signatur gibt, wird die Methode ausgeblendet und nicht überschrieben. Daher ist es unerheblich, die abstrakte Methode als statisch zu deklarieren, da sie niemals den Körper erhält. Daher Fehler beim Kompilieren.
Eine statische Methode kann ohne eine Instanz der Klasse aufgerufen werden. In Ihrem Beispiel können Sie foo.bar2 () aufrufen, nicht jedoch foo.bar (), da Sie für bar eine Instanz benötigen. Der folgende Code würde funktionieren:
foo var = new ImplementsFoo();
var.bar();
Wenn Sie eine statische Methode aufrufen, wird immer derselbe Code ausgeführt. Selbst wenn Sie im obigen Beispiel bar2 in ImplementsFoo neu definieren, würde ein Aufruf von var.bar2 () foo.bar2 () ausführen.
Wenn bar2 jetzt keine Implementierung hat (was abstrakt bedeutet), können Sie eine Methode ohne Implementierung aufrufen. Das ist sehr schädlich.
Ich glaube, ich habe die Antwort auf diese Frage in der Form gefunden, warum die Methoden einer Schnittstelle (die wie abstrakte Methoden in einer übergeordneten Klasse funktionieren) nicht statisch sein können. Hier ist die vollständige Antwort (nicht meine)
Grundsätzlich können statische Methoden zur Kompilierungszeit gebunden werden, da Sie zum Aufrufen eine Klasse angeben müssen. Dies unterscheidet sich von Instanzmethoden, für die die Klasse der Referenz, von der aus Sie die Methode aufrufen, zur Kompilierungszeit möglicherweise unbekannt ist (daher kann der aufgerufene Codeblock nur zur Laufzeit bestimmt werden).
Wenn Sie eine statische Methode aufrufen, kennen Sie bereits die Klasse, in der sie implementiert ist, oder direkte Unterklassen davon. Wenn Sie definieren
abstract class Foo {
abstract static void bar();
}
class Foo2 {
@Override
static void bar() {}
}
Dann ist jeder Foo.bar();
Anruf offensichtlich illegal und wird immer verwendet Foo2.bar();
.
Vor diesem Hintergrund besteht der einzige Zweck einer statischen abstrakten Methode darin, Unterklassen zur Implementierung einer solchen Methode zu erzwingen. Sie könnten zunächst denken, dass dies SEHR falsch ist, aber wenn Sie einen generischen Typparameter <E extends MySuperClass>
haben, wäre es schön, dies über eine Schnittstelle zu garantieren, die dies E
kann .doSomething()
. Beachten Sie, dass Generika aufgrund von Typlöschungen nur zur Kompilierungszeit vorhanden sind.
Wäre es also nützlich? Ja, und vielleicht erlaubt Java 8 deshalb statische Methoden in Schnittstellen (allerdings nur mit einer Standardimplementierung). Warum nicht abstrakte statische Methoden mit einer Standardimplementierung in Klassen? Einfach, weil eine abstrakte Methode mit einer Standardimplementierung tatsächlich eine konkrete Methode ist.
Warum nicht abstrakte / Schnittstellen-statische Methoden ohne Standardimplementierung? Anscheinend nur aufgrund der Art und Weise, wie Java identifiziert, welchen Codeblock es ausführen muss (erster Teil meiner Antwort).
Da die abstrakte Klasse ein OOPS-Konzept ist und statische Elemente nicht Teil von OOPS sind ...
Jetzt können wir statische vollständige Methoden in der Schnittstelle deklarieren und die Schnittstelle ausführen, indem wir die Hauptmethode innerhalb einer Schnittstelle deklarieren
interface Demo
{
public static void main(String [] args) {
System.out.println("I am from interface");
}
}
Die Idee einer abstrakten statischen Methode wäre, dass Sie diese bestimmte abstrakte Klasse nicht direkt für diese Methode verwenden können, sondern nur die erste Ableitung diese statische Methode implementieren darf (oder für Generika: die tatsächliche Klasse des generischen Sie verwenden).
Auf diese Weise können Sie beispielsweise eine abstrakte Klasse sortableObject oder sogar eine Schnittstelle mit (automatisch) abstrakten statischen Methoden erstellen, die die Parameter der Sortieroptionen definiert:
public interface SortableObject {
public [abstract] static String [] getSortableTypes();
public String getSortableValueByType(String type);
}
Jetzt können Sie ein sortierbares Objekt definieren, das nach den Haupttypen sortiert werden kann, die für alle diese Objekte gleich sind:
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
}
}
Jetzt können Sie eine erstellen
public class SortableList<T extends SortableObject>
Das kann die Typen abrufen, ein Popup-Menü erstellen, um einen Typ zum Sortieren auszuwählen und die Liste neu abzurufen, indem die Daten von diesem Typ abgerufen werden, sowie eine Add-Funktion haben, die, wenn ein Sortiertyp ausgewählt wurde, automatisch ausgeführt werden kann -sortieren Sie neue Elemente in. Beachten Sie, dass die Instanz von SortableList direkt auf die statische Methode von "T" zugreifen kann:
String [] MenuItems = T.getSortableTypes();
Das Problem bei der Verwendung einer Instanz besteht darin, dass die SortableList möglicherweise noch keine Elemente enthält, aber bereits die bevorzugte Sortierung bereitstellen muss.
Cheerio, Olaf.
Erstens ein wichtiger Punkt zu abstrakten Klassen - Eine abstrakte Klasse kann nicht instanziiert werden (siehe Wiki ). Sie können also keine Instanz einer abstrakten Klasse erstellen .
Die Art und Weise, wie Java mit statischen Methoden umgeht, besteht darin, die Methode für alle Instanzen dieser Klasse freizugeben.
Wenn Sie eine Klasse nicht instanziieren können, kann diese Klasse keine abstrakten statischen Methoden haben, da eine abstrakte Methode erweitert werden muss.
Boom.
Gemäß Java- Dokument :
Eine statische Methode ist eine Methode, die der Klasse zugeordnet ist, in der sie definiert ist, und nicht einem Objekt. Jede Instanz der Klasse teilt ihre statischen Methoden
In Java 8 sind neben Standardmethoden auch statische Methoden in einer Schnittstelle zulässig. Dies erleichtert uns die Organisation von Hilfsmethoden in unseren Bibliotheken. Wir können statische Methoden, die für eine Schnittstelle spezifisch sind, in derselben Schnittstelle und nicht in einer separaten Klasse aufbewahren.
Ein schönes Beispiel dafür ist:
list.sort(ordering);
anstatt
Collections.sort(list, ordering);
Ein weiteres Beispiel für die Verwendung statischer Methoden finden Sie auch in doc selbst:
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));
}
}
Weil 'abstrakt' bedeutet, dass die Methode überschrieben werden soll und man 'statische' Methoden nicht überschreiben kann.
Reguläre Methoden können abstrakt sein, wenn sie von Unterklassen überschrieben und mit Funktionen versehen werden sollen. Stellen Sie sich vor, die Klasse Foo
wird um Bar1, Bar2, Bar3
usw. erweitert . Jede hat also ihre eigene Version der abstrakten Klasse, je nach ihren Bedürfnissen.
Jetzt gehören statische Methoden per Definition zur Klasse, sie haben nichts mit den Objekten der Klasse oder den Objekten ihrer Unterklassen zu tun. Sie brauchen sie nicht einmal zu existieren, sie können verwendet werden, ohne die Klassen zu instanziieren. Daher müssen sie einsatzbereit sein und können sich nicht auf die Unterklassen verlassen, um ihnen Funktionen hinzuzufügen.
Da abstract ein Schlüsselwort ist, das auf Abstract-Methoden angewendet wird, geben Sie keinen Body an. Und wenn wir über statisches Schlüsselwort sprechen, gehört es zum Klassenbereich.
Sie können dies mit Schnittstellen in Java 8 tun.
Dies ist die offizielle Dokumentation dazu:
https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
Denn wenn eine Klasse eine abstrakte Klasse erweitert, muss sie abstrakte Methoden überschreiben, und das ist obligatorisch. Und da statische Methoden Klassenmethoden sind, die zur Kompilierungszeit aufgelöst werden, während überschriebene Methoden Instanzmethoden sind, die zur Laufzeit und nach dynamischem Polymorphismus aufgelöst werden.