233 votes

Constructeur d'une classe abstraite en C#

Pourquoi est-il possible d'écrire un constructeur pour une classe abstraite en C# ?
Pour autant que je sache, nous ne pouvons pas instancier une classe abstraite alors à quoi sert-elle ?
Vous ne pouvez pas instancier la classe, n'est-ce pas ?

304voto

Craig Suchanec Points 3585

Parce qu'il pourrait y avoir une façon standard d'instancier les données dans la classe abstraite. De cette façon, les classes qui héritent de cette classe peuvent appeler le constructeur de base.

public abstract class A{

    private string data;

    protected A(string myString){
      data = myString;
    }

}

public class B : A {

     B(string myString) : base(myString){}

}

3 votes

Mais la classe abstraite est définie comme une classe que l'on ne peut pas instancier. Si je l'utilise pour initialiser une variable en lecture seule sur la classe de base qui est abstraite, est-ce correct ?

6 votes

Oui, si je vous comprends bien. Vous ne pouvez pas instancier la classe abstraite elle-même mais la classe dérivée possède toujours tous les éléments de la classe de base. Ce n'est pas seulement valable de le faire, c'est l'une des principales raisons pour lesquelles vous le feriez.

0 votes

Ok, maintenant si j'ai une classe abstraite de premier niveau qui hérite d'une autre classe abstraite (deuxième niveau) et que la troisième classe (pas une classe abstraite) hérite de la classe abstraite de deuxième niveau, comment puis-je initialiser une variable en lecture seule qui est déclarée sur la classe abstraite de premier niveau à partir du code de la troisième classe normale ? Je dois remonter de deux niveaux jusqu'au code.

272voto

Eric Lippert Points 300275

Pour autant que je sache, on ne peut pas instancier une classe abstraite

C'est là que se trouve votre erreur. Bien sûr, vous pouvez instancier une classe abstraite.

abstract class Animal {}
class Giraffe : Animal {}
...
Animal animal = new Giraffe();

Il y a un exemple d'animal juste là. Vous instanciez une classe abstraite en créant une classe concrète dérivée de celle-ci, et en l'instanciant. Rappelez-vous, une instance d'une classe concrète dérivée est également une instance de sa classe de base abstraite. Une instance de Girafe est également une instance d'Animal, même si Animal est abstrait.

Étant donné que vous pouvez instancier une classe abstraite, elle doit avoir un constructeur comme n'importe quelle autre classe, pour s'assurer que ses invariants sont respectés.

Maintenant, un statique est une classe que vous ne pouvez pas instancier, et vous remarquerez qu'il n'est pas légal de faire un constructeur d'instance dans une classe statique.

3 votes

D'un point de vue terminologique, si Foo est un type concret héritable, et DerivedFoo:Foo Quel terme utiliseriez-vous pour décrire une instance d'objet de tas qui déclarera son type comme étant Foo à la différence de DerivedFoo ? J'aurais tendance à utiliser l'expression "une instance de T" pour faire référence à quelque chose dont exact Sinon, j'aurais tendance à dire quelque chose comme "un T ou un dérivé", "un dérivé de T", "une implémentation de T" ou "quelque chose qui satisfait T", selon que T est une classe concrète, une classe abstraite, une interface ou une contrainte.

33 votes

En utilisant cette logique, vous pouvez obtenir des instances d'interfaces :-)

9 votes

@Eric msdn.microsoft.com/fr/us/library/sf985hc5.aspx Dit qu'une classe abstraite ne peut pas être instanciée

25voto

Rodrick Chapman Points 2981

C'est un moyen de faire respecter un ensemble d'invariants de la classe abstraite. C'est-à-dire que, peu importe ce que fait la sous-classe, vous voulez vous assurer que certaines choses sont toujours vraies pour la classe de base... exemple :

abstract class Foo
{
    public DateTime TimeCreated {get; private set;}

    protected Foo()
    {
         this.TimeCreated = DateTime.Now;
    }
}

abstract class Bar : Foo
{
    public Bar() : base() //Bar's constructor's must call Foo's parameterless constructor.
    { }
}

Ne considérez pas un constructeur comme le double de la fonction new opérateur. Le seul but du constructeur est de s'assurer que vous avez un objet dans un état valide avant de commencer à l'utiliser. Il se trouve que nous généralement l'appeler par le biais d'un new opérateur.

9 votes

Vous n'avez pas besoin d'appeler base() sur le constructeur de la classe dérivée. Il sera appelé automatiquement, car c'est le constructeur sans paramètre. Cela signifie que votre constructeur est équivalent à public Bar() {} .

1 votes

@RobertKoritnik - c'est étrange car je ne peux pas me rappeler ou même imaginer un moment où je ne savais pas cela, mais c'est ainsi.

1 votes

Note complémentaire/commentaire : j'aime le fait que vous ayez utilisé les mots "impair" et "pair" dans la même phrase.

5voto

Ross Anderson Points 116

Il est là pour appliquer une logique d'initialisation requise par toutes les implémentations de votre classe abstraite, ou toute méthode que vous avez implémentée sur votre classe abstraite (toutes les méthodes de votre classe abstraite ne doivent pas être abstraites, certaines peuvent être implémentées).

Toute classe qui hérite de votre classe de base abstraite sera obligée d'appeler le constructeur de la base.

1voto

user3579354 Points 1

Normalement, les constructeurs consistent à initialiser les membres d'un objet en cours de création. Dans le concept d'héritage, chaque constructeur de classe dans la hiérarchie d'héritage est responsable de l'instanciation de ses propres variables membres. Ceci est logique car l'instanciation doit être faite là où les variables sont définies.

Puisqu'une classe abstraite n'est pas complètement abstraite (contrairement aux interfaces), elle est composée de membres abstraits et concrets, et les membres qui ne sont pas abstraits doivent être initialisés, ce qui est fait dans les constructeurs de la classe abstraite, il est nécessaire d'avoir des constructeurs dans la classe abstraite. Bien entendu, les constructeurs de la classe abstraite ne peuvent être appelés que par les constructeurs de la classe dérivée.

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