Gibt es eine Möglichkeit, eine Methode zu erstellen, die nicht abstrakt ist, aber überschrieben werden muss?

Lesezeit: 5 Minuten

Gibt es eine Möglichkeit, untergeordnete Klassen zu zwingen, eine nicht abstrakte Methode der Superklasse zu überschreiben?

Ich muss in der Lage sein, Instanzen der übergeordneten Klasse zu erstellen, aber wenn eine Klasse diese Klasse erweitert, muss sie ihre eigene Definition einiger Methoden angeben.

  • Mir ist aufgefallen, dass es eine Ablehnung gab. Es macht mir nichts aus, aber bitte erklären Sie auch den Grund für die Ablehnung.

    Benutzer517491

    20. Oktober 2011 um 11:24 Uhr

  • Wenn eine Methode nicht abstrakt ist, hat sie eine bereitgestellte Implementierung. Wenn es eine bereitgestellte Implementierung hätte, aber “abstrakt” wäre, wäre die bereitgestellte Implementierung nutzlos, da sie durch die Überschreibung verworfen würde. Also warum willst du das?

    – Raedwald

    20. Oktober 2011 um 11:52 Uhr

  • @Raedwald Ich habe in der Frage erwähnt, dass ich auch Instanzen der Elternklasse erstellen können muss. Wie Elternteil p=neues Elternteil(); Aber wenn eine Methode in der Parent-Klasse abstrakt ist, kann ich das nicht tun … Das ist der springende Punkt.

    Benutzer517491

    20. Oktober 2011 um 12:44 Uhr


  • Dies scheint ein Wartungsproblem zu sein, das darauf wartet, passiert zu werden. In Fällen, in denen Kinder eine andere Implementierung der Methode als die Basisklasse bereitstellen müssen, ist es angemessen, eine Schnittstelle zu definieren und die abstrakte Basisklasse eine Ausnahme auslösen zu lassen. Wenn Sie erwarten, dass Ihre konkrete Klasse in Unterklassen unterteilt wird, ist Ihr Design wahrscheinlich suboptimal. Siehe Open-Closed-Prinzip.

    – Visionäre Softwarelösungen

    20. Oktober 2011 um 18:08 Uhr

  • Sie können die Methode der Superklasse so einstellen, dass sie eine RuntimeException auslöst, dann wissen Sie zumindest, dass Sie sie beim Testen überschreiben mussten.

    – Rob Fuchs

    25. Oktober 2011 um 12:17 Uhr

Benutzer-Avatar
Joachim Sauer

Soweit ich weiß, gibt es keine direkte vom Compiler erzwungene Möglichkeit, dies zu tun.

Sie könnten es umgehen, indem Sie nicht Die übergeordnete Klasse instanziierbar machen, aber stattdessen eine Factory-Methode bereitstellen, die eine Instanz einer (möglichen privaten) Unterklasse mit der Standardimplementierung erstellt:

public abstract class Base {
  public static Base create() {
    return new DefaultBase();
  }

  public abstract void frobnicate();

  static class DefaultBase extends Base {
    public void frobnicate() {
      // default frobnication implementation
    }
  }
}

Du kippen schreiben new Base() jetzt, aber du kannst es tun Base.create() um die Standardimplementierung zu erhalten.

  • Ich möchte darauf hinweisen, dass eine untergeordnete Klasse nicht in der Lage sein wird, die Standardimplementierung der übergeordneten Klasse durch Aufrufen abzurufen super.frobincate() da eine untergeordnete Klasse erben wird Base und nicht DefaultBase. Ansonsten ist dies eine großartige Lösung, denke ich.

    – Antonius

    20. Oktober 2011 um 12:14 Uhr


Benutzer-Avatar
Daniel Priden

Wie andere bereits betont haben, können Sie dies nicht direkt tun.

Aber eine Möglichkeit, dies zu tun, ist die Verwendung von Strategiemusterso:

public class Base {
    private final Strategy impl;

    // Public factory method uses DefaultStrategy
    // You could also use a public constructor here, but then subclasses would
    // be able to use that public constructor instead of the protected one
    public static Base newInstance() {
        return new Base(new DefaultStrategy());
    }

    // Subclasses must provide a Strategy implementation
    protected Base(Strategy impl) {
        this.impl = impl;
    }

    // Method is final: subclasses can "override" by providing a different
    // implementation of the Strategy interface
    public final void foo() {
        impl.foo();
    }

    // A subclass must provide an object that implements this interface
    public interface Strategy {
        void foo();
    }

    // This implementation is private, so subclasses cannot access it
    // It could also be made protected if you prefer
    private static DefaultStrategy implements Strategy {
        @Override
        public void foo() {
            // Default foo() implementation goes here
        }
    }
}

  • Schön gemacht. Dies ist wahrscheinlich die eleganteste Art, mit diesem Problem umzugehen.

    – Visionäre Softwarelösungen

    21. Oktober 2011 um 0:23 Uhr

  • Dies ist der bessere Weg, weil es schlechtes Design ist, Methoden zu überschreiben, die Definitionen haben. Alle Methoden sollten final, abstrakt oder leer sein.

    – David

    27. Oktober 2011 um 16:50 Uhr

  • Aah, ich möchte diese Antwort als akzeptiert markieren, aber mein altes SO-Konto ist verloren :'(

    – Syed Aqeel Ashiq

    6. Juni um 5:45


Erwägen Sie, mit dieser Methode eine Schnittstelle zu erstellen. Die Nachkommen der Klasse müssen es implementieren.

  • Wie würde das helfen? Wenn die Basisklasse instanziierbar sein muss, muss sie sie auch implementieren. Dies würde die Notwendigkeit der abgeleiteten Klassen, ihre Methoden zu implementieren, zunichte machen.

    – Joachim Sauer

    20. Oktober 2011 um 7:33 Uhr

  • Es besteht keine Notwendigkeit, es durch die Basisklasse zu implementieren. Fragen Sie nach einer Schnittstelleninstanz, wo Sie das abgeleitete Objekt verwenden müssen, nicht nach einer Basisklasseninstanz. Dies zwingt abgeleitete Klassen, eine Schnittstellenimplementierung zu haben. Sie können auch im Methodentext nach einem Basisklassentyp suchen.

    – Iwan Nikitin

    20. Oktober 2011 um 12:26 Uhr


Ich denke, der einfachste Weg ist, eine abstrakte Klasse zu erstellen, die von der Basisklasse erbt:


public class Base {
    public void foo() {
        // original method
    }
}

abstract class BaseToInheritFrom extends Base {
    @Override
    public abstract void foo();
}

class RealBaseImpl extends BaseToInheritFrom {
    @Override
    public void foo() {
        // real impl
    }
}

Nein, das ist der ganze Sinn einer abstrakten Methode. Was ist Ihr Anwendungsfall? Vielleicht können wir darüber nachdenken, basierend auf dem zugrunde liegenden Bedarf.

Wie wäre es damit: Verwenden Sie in der Standardimplementierung der Methode Reflektion, um die genaue Klasse des Objekts zu erhalten. Wenn die Klasse nicht genau mit Ihrer Basisklasse übereinstimmt, lösen Sie eine RuntimeException oder ein Äquivalent aus.

public class Parent {

    public void defaultImpl(){
        if(this.getClass() != Parent.class){
            throw new RuntimeException();
        }
    }

}

Benutzer-Avatar
Gemeinschaft

Da ist ein Grund es ist nicht möglich!

Die abgeleitete Klasse könnte einfach Anruf die Implementierung der Basisklasse beim Überschreiben der Methode.

Was bringt es also, die Klasse zu zwingen, Ihre Methode zu überschreiben? Ich glaube nicht, dass es einen Nutzen gibt.

  • Der konzeptionelle Grund ist dieser: dort tut Es gibt eine Anmerkung, die angibt, dass eine überschreibende Methode die überschriebene aufrufen muss. Durch die Kombination dieser beiden Anmerkungen können Sie eine Methode erstellen, die einige grundlegende Aufgaben erledigt, die für alle Unterklassen gleich sein müssen, aber nicht ausreichen, da Sie bereits wissen, dass dies nicht ausreichen wird, und Sie sicher sein möchten, dass sich die Unterklasse daran erinnert Beende die Aufgabe.

    – dfeuer

    31. März 2014 um 1:57 Uhr

  • @dfeuer: Wie könnten Sie möglicherweise verhindern, dass die abgeleitete Klasse die Basisklassenmethode “aufruft”. if (false) super.Foo();?

    – Benutzer541686

    31. März 2014 um 2:00 Uhr

  • Die Absicht (oder zumindest mein Absicht, als ich nach dieser Frage suchte) bestand nicht darin, sicherzustellen, dass niemand sie absichtlich brach, sondern sicherzustellen, dass niemand sie versehentlich brach!

    – dfeuer

    31. März 2014 um 2:12 Uhr

  • @dfeuer: Oh, verstehe, interessant … Ich hatte den Eindruck, dass es bei der Frage wirklich um die Durchsetzung ging. Um Fehler zu vermeiden, bin ich mir nicht sicher, es könnte ein nettes Feature gewesen sein. Ich denke, in Java wollten sie es einfach halten, wenn es nicht unbedingt notwendig ist?

    – Benutzer541686

    31. März 2014 um 2:46 Uhr


1381240cookie-checkGibt es eine Möglichkeit, eine Methode zu erstellen, die nicht abstrakt ist, aber überschrieben werden muss?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy