web-dev-qa-db-fra.com

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-il?
Vous ne pouvez pas instancier la classe, non?

170
Mulder

Parce qu'il peut exister une méthode standard pour instancier des données dans la classe abstraite. De cette façon, vous pouvez avoir des classes qui héritent de cette classe, appelez 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){}

}
216
Craig Suchanec

Autant que je sache, nous ne pouvons pas instancier une classe abstraite

Il y a votre erreur juste là. Bien sûr, vous pouvez instancier une classe abstraite.  

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

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

Etant donné que vous pouvez instancier une classe abstraite, elle doit avoir un constructeur comme toute autre classe pour garantir que ses invariants sont satisfaits. 

Maintenant, une classe static est une classe que vous ne pouvez pas instancier, et vous remarquerez qu'il est illégal de créer un constructeur d'instance dans une classe statique.

250
Eric Lippert

C'est un moyen d'imposer un ensemble d'invariants de la classe abstraite. En d’autres termes, quelle que soit la sous-classe, vous voulez vous assurer que certaines choses sont toujours vraies de la classe de base ...

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 l'opérateur new. Le seul objectif du constructeur est de vous assurer qu'un objet est dans un état valide avant de commencer à l'utiliser. Il se trouve que nous habituellement l'appelons via un opérateur new.

17
Rodrick Chapman

Il est là pour appliquer une logique d'initialisation requise par toutes les implémentations de votre classe abstraite, ou toutes les méthodes que vous avez implémentées sur votre classe abstraite (toutes les méthodes de votre classe abstraite ne doivent pas nécessairement ê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 base.

5
Ross Anderson

Normalement, les constructeurs impliquent d'initialiser les membres d'un objet en cours de création. Dans le concept d'héritage, chaque constructeur de classe de la hiérarchie d'héritage est généralement responsable de l'instanciation de ses propres variables membres. Cela a du sens car l’instanciation doit être faite où les variables sont définies. 

Comme une classe abstraite n'est pas complètement abstraite (contrairement aux interfaces), elle est un mélange de membres abstraits et concrets, et les membres non abstraits doivent être initialisés, ce qui est fait dans les constructeurs de la classe abstraite. dans la classe abstraite. Bien entendu, les constructeurs de la classe abstraite ne peuvent être appelés qu'à partir des constructeurs de la classe dérivée.

1
Zafar Ameem

La définition d'un constructeur avec une classe de stockage publique ou interne dans une classe concrète héritable Thing définit efficacement deux méthodes:

  • Une méthode (que j'appellerai InitializeThing) qui agit sur this, n'a aucune valeur de retour et ne peut être appelée qu'à partir des méthodes Thing's CreateThing et InitializeThing et des méthodes InitializeXXX des sous-classes.

  • Une méthode (que j'appellerai CreateThing) qui retourne un objet du type désigné par le constructeur et se comporte essentiellement comme:

    Thing CreateThing(int whatever)
    {
        Thing result = AllocateObject<Thing>();
        Thing.initializeThing(whatever);
    }
    

Les classes abstraites créent effectivement des méthodes de la première forme seulement. Conceptuellement, il n’ya aucune raison pour que les deux "méthodes" décrites ci-dessus aient besoin des mêmes spécificateurs d’accès; dans la pratique, cependant, il est impossible de spécifier leur accessibilité différemment. Notez qu'en termes d'implémentation réelle, du moins dans .NET, CreateThing n'est pas réellement implémenté en tant que méthode appelable, mais représente plutôt une séquence de code qui est insérée dans une instruction newThing = new Thing(23);.

0
supercat

une classe abstraite peut avoir des variables membres qui doivent être initialisées. Elles peuvent donc être initialisées dans le constructeur de la classe abstraite. Ce constructeur est appelé lorsque l'objet de la classe dérivée est initialisé.

0
waqar ahmed

De https://msdn.Microsoft.com/en-us/library/ms182126.aspx

Les constructeurs sur les types abstraits ne peuvent être appelés que par des types dérivés. Étant donné que les constructeurs publics créent des instances d'un type et que vous ne pouvez pas créer d'instances d'un type abstrait, un type abstrait possédant un constructeur public est conçu de manière incorrecte.

Etant donné que seules les classes dérivées peuvent utiliser un constructeur de classe abstraite, un constructeur de classe abstraite, si nécessaire, doit être déclaré en tant que protected.

Cependant, ledit compilateur VS ne se plaindra pas (avec les règles par défaut) lors de la déclaration de constructeurs publics dans des classes abstraites, mais ne permettra pas la création d'une nouvelle instance. 

0
Ahmad

Moi aussi, je veux faire de la brillance sur une surface abstraite Toutes les réponses ont couvert presque toutes les choses. Toujours mes 2 cents

les classes abstraites sont des classes normales à quelques exceptions près

  1. Aucun client/consommateur de cette classe ne peut créer un objet de cette classe Cela ne signifie jamais que son constructeur n'appellera jamais. Sa classe dérivée peut choisir le constructeur à appeler (comme indiqué dans certaines réponses).
  2. Il peut avoir une fonction abstraite.
0
Sumit Kapadia

Vous avez tout à fait raison. Nous ne pouvons pas instancier une classe abstraite car les méthodes abstraites n’ont pas de corps, ce qui signifie qu’il est impossible de les implémenter. Mais il peut y avoir des scénarios dans lesquels vous souhaitez initialiser certaines variables de la classe de base. Vous pouvez le faire en utilisant le mot-clé base comme suggéré par @Rodrick. Dans de tels cas, nous devons utiliser des constructeurs dans notre classe abstraite.

0
Rohan Rao

Vous pouvez l'instancier après avoir implémenté toutes les méthodes. Ensuite, le constructeur sera appelé.

0
duedl0r