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.