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.

3voto

curioustechizen Points 4841

Que diriez-vous de ceci : dans l'implémentation par défaut de la méthode, utilisez la réflexion pour obtenir la classe exacte de l'objet. Si la classe ne correspond pas exactement à votre classe de base, lancez une RuntimeException ou un équivalent.

public class Parent {

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

}

3voto

Mehrdad Points 70493

Hay un raison ce n'est pas possible !

La classe dérivée pourrait simplement appelez l'implémentation de la classe de base lors de la surcharge de la méthode.

Alors quel est l'intérêt de forcer la classe à surcharger votre méthode ? Je ne pense pas qu'il y ait un avantage.

2voto

Ravi Bhatt Points 2025

La réponse est non. Vous pouvez refaire la conception en utilisant le modèle de conception des modèles. Cela peut vous aider.

Vous pouvez également faire en sorte que vos classes enfant mettent en œuvre une interface. L'interface peut être implémentée ou non par la super classe.

1voto

Edwin Buck Points 33097

Vous pouvez toujours faire en sorte que la classe de base ait une méthode qui lève une exception.

Techniquement, la classe de base a défini la méthode, mais elle n'est pas utilisable sans surcharge de la méthode. Dans un tel cas, je préfère une exception d'exécution, car elle ne nécessite pas d'instruction throws explicite. Voici un exemple

public class Parent {

  public void doStuff() {
    throw new RuntimeException("doStuff() must be overridden");
  }

}

public class Child extends Parent {

  @Override
  public void doStuff() {
    ... all is well here ...
  }

}

L'inconvénient est que cela n'empêche pas la création de Base Cependant, quiconque tente d'utiliser l'une des méthodes "must be overridden" se rendra vite compte qu'il aurait dû surcharger la classe.

Bien que cette solution réponde bien à la description de la demande, votre application aurait probablement intérêt à ne pas exiger une solution comme celle-ci. Il vaut mieux éviter les pannes d'exécution avec des vérifications du compilateur, ce que fournit le mot-clé abstrait.

1voto

KeithS Points 36130

Je vais refléter les autres réponses et dire qu'il n'y a aucun moyen de forcer les classes dérivées à surcharger une méthode non-abstraite. Le but de rendre une méthode abstraite est de définir qu'une méthode avec cette signature doit exister, mais ne peut pas être spécifiée au niveau de la base et doit donc être spécifiée au niveau dérivé. S'il existe une implémentation fonctionnelle et non triviale (c'est-à-dire qu'elle n'est pas vide et qu'elle ne se contente pas de lever une exception ou d'afficher un message) d'une méthode au niveau de la base, elle n'est pas strictement nécessaire pour qu'un appel à la méthode par un consommateur de la classe dérivée réussisse. Ainsi, le compilateur n'a pas besoin d'imposer la surcharge d'une méthode qui peut s'exécuter avec succès au niveau de base ou au niveau dérivé.

Dans les situations où vous voudriez qu'une classe dérivée surcharge votre implémentation de travail, il devrait être assez évident que l'implémentation de base ne fait pas ce que les consommateurs de la classe dérivée voudront ; la classe de base n'a pas assez d'implémentation, ou la mauvaise. Dans ces cas, vous devez croire qu'un programmeur dérivant de votre classe saura ce qu'il fait et saura donc que la méthode doit être surchargée parce qu'elle ne produit pas la bonne réponse dans le contexte de l'utilisation de son nouvel objet.

Je pense à une chose que vous pourriez faire. Il faudrait une base abstraite, avec une implémentation "par défaut" scellée (finale pour les Javaheads). De cette façon, il y a une implémentation de base de la méthode qui est facilement disponible pour être utilisée comme s'il s'agissait d'une classe "de base", mais afin de définir une classe différente pour un nouveau scénario, vous devez revenir à la classe abstraite, et êtes donc obligé de réimplémenter la méthode. Cette méthode pourrait être la seule chose abstraite de la classe, ce qui vous permettrait toujours d'utiliser les implémentations de base des autres méthodes :

public abstract class BaseClass
{
   public abstract void MethodYouMustAlwaysOverride();

   public virtual void MethodWithBasicImplementation() { ... }
}

public final class DefaultClass:BaseClass
{
   public override void MethodYouMustAlwaysOverride() { ... }

   //the base implementation of MethodWithBasicImplementation 
   //doesn't have to be overridden
}

...

public class DerivedClass:BaseClass
{
   //Because DefaultClass is final, we must go back to BaseClass,
   //which means we must reimplement the abstract method
   public override void MethodYouMustAlwaysOverride() { ... }

   //again, we can still use MethodWithBasicImplementation, 
   //or we can extend/override it
   public override void MethodWithBasicImplementation() { ... }
}

Cependant, cela présente deux inconvénients. Premièrement, parce que vous n'avez pas accès à l'implémentation de DefaultClass par le biais de l'héritage, vous ne pouvez pas étendre l'implémentation de DefaultClass, ce qui signifie que pour faire ce que DefaultClass fait, plus un peu plus, vous devez réécrire le code de DefaultClass, violant ainsi le DRY. Deuxièmement, ceci ne fonctionne que pour un seul niveau d'héritage, parce que vous ne pouvez pas forcer l'overriding si vous autorisez l'héritage de DerivedClass.

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