58 votes

Existe-t-il un moyen de créer une méthode qui n'est pas abstraite mais qui doit être surchargée ?

Existe-t-il un moyen de forcer les classes enfant à surcharger une méthode non abstraite de la super classe ?

Je dois pouvoir créer des instances de la classe mère, mais si une classe étend cette classe, elle doit donner sa propre définition de certaines méthodes.

37voto

Joachim Sauer Points 133411

Il n'y a pas de moyen direct imposé par le compilateur pour faire cela, pour autant que je sache.

Vous pouvez contourner ce problème en pas en rendant la classe parente instanciable, mais en fournissant à la place une méthode de fabrique qui crée une instance d'une sous-classe (éventuellement privée) qui a l'implémentation par défaut :

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
    }
  }
}

Vous ne peut pas écrire new Base() maintenant, mais vous pouvez faire Base.create() pour obtenir l'implémentation par défaut.

24voto

Daniel Pryden Points 22167

Comme d'autres l'ont souligné, vous ne pouvez pas le faire directement.

Mais une façon de le faire est d'utiliser l'option Modèle de stratégie comme ça :

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
        }
    }
}

6voto

Ivan Nikitin Points 1200

Envisagez de créer une interface avec cette méthode. Les descendants de la classe devront l'implémenter.

5voto

s106mo Points 711

Je pense que le moyen le plus simple est de créer une classe abstraite qui hérite de la classe de base :

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
    }
}

3voto

mjaggard Points 1020

Non, c'est tout l'intérêt d'une méthode abstraite. Quel est votre cas d'utilisation ? Nous pouvons peut-être y réfléchir en fonction du besoin sous-jacent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X