web-dev-qa-db-fra.com

C # - Faire en sorte que toutes les classes dérivées appellent le constructeur de classe de base

J'ai un personnage de classe de base qui en a plusieurs classes. La classe de base a différents champs et méthodes.

Toutes mes classes dérivées utilisent le même constructeur de classe de base, mais si je ne redéfinis pas le constructeur dans mes classes dérivées, j'obtiens l'erreur:

Erreur: la classe "classe enfant" ne contient pas de constructeur qui accepte ce nombre d'arguments

Je ne veux pas redéfinir le constructeur dans chaque classe dérivée parce que si le constructeur change, je dois le changer dans chaque classe unique qui, pardonner tout malentendu, va à l'encontre de l'idée d'écrire une seule fois du code?

46
Tom

Vous ne devez redéclarer les constructeurs, car ils ne sont en fait pas hérités. Cela a du sens si vous pensez que les constructeurs sont un peu comme des méthodes statiques à certains égards.

En particulier, vous ne voudriez pas vouloir que tous les constructeurs soient hérités automatiquement - après tout, cela signifierait que la classe every aurait un constructeur sans paramètre, comme object lui-même le fait.

Si vous voulez simplement appeler le constructeur de la classe de base, vous n'avez pas besoin d'écrire de code dans le corps du constructeur - passez simplement les arguments à la classe de base comme indiqué par Waleed.

Si votre classe de base commence à exiger plus d'informations, il est naturel que vous deviez changer toutes les classes dérivées - et en fait tout ce qui appelle les constructeurs de ces classes - car elles doivent fournir les informations. Je sais que cela peut sembler une douleur, mais c'est juste une conséquence naturelle de ce que font les constructeurs.

45
Jon Skeet

Vous pouvez utiliser la syntaxe suivante pour appeler le constructeur de classe de base à partir des classes qui en dérivent:

public DerivedClass() : base() {
    // Do additional work here otherwise you can leave it empty
}

Cela appellera le constructeur de base en premier, puis il exécutera toute instruction supplémentaire, le cas échéant, dans ce constructeur dérivé.

Notez que si le constructeur de base prend des arguments, vous pouvez le faire:

public DerivedClass(int parameter1, string parameter2) 
    : base(parameter1, parameter2) {
    // DerivedClass parameter types have to match base class types
    // Do additional work here otherwise you can leave it empty
}

Vous pouvez trouver plus d'informations sur les constructeurs dans la page suivante:

https://docs.Microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/using-constructors

Dans une classe dérivée, si un constructeur de classe de base n'est pas appelé explicitement à l'aide du mot clé base, le constructeur par défaut, s'il en existe un, est appelé implicitement.

73
Waleed Al-Balooshi

J'ai eu le même problème, et je l'ai résolu en remplaçant mon constructeur par une méthode d'usine comme celle-ci:

A est la classe parente.

public static T getChild<T>(int number) where T:A, new()
{
    T child = new T();
    T._number = number;
    return child;

}

Vous pouvez créer une classe enfant avec

Child b = A.getChild<Child>(2);

5
jasdefer

Une sorte d'alternative pourrait être de s'appuyer sur un conteneur d'Injection de dépendances pour initialiser vos objets, de cette façon la référence à la classe de base (qui pourrait être l'appel au constructeur de base ou une autre méthode d'initialisation) serait "externalisée" au conteneur DI.

Je ne sais pas si cela a du sens pour votre cas ou non

1
t3mujin