127 votes

Le constructeur de la classe de base sera-t-il automatiquement appelé ?

class Person
{
    public int age;
    public Person()
    {
        age = 1;
    }
}

class Customer : Person
{
    public Customer()
    {
        age += 1;
    }
}

Customer customer = new Customer();

L'âge du client serait-il de 2 ans ? Il semble que le constructeur de la classe de base sera appelé quoi qu'il arrive. Si c'est le cas, pourquoi avons-nous besoin d'appeler base à la fin parfois ?

public Customer() : base()
{
    .............
}

115voto

Tejs Points 23834

C'est tout simplement la façon dont le C# va fonctionner. Les constructeurs de chaque type dans la hiérarchie des types seront appelés dans l'ordre suivant : le plus bas -> le plus dérivé.

Donc dans votre cas particulier, il appelle Person() et ensuite Customer() dans les commandes du constructeur. La raison pour laquelle vous devez parfois utiliser le base Le constructeur est utilisé lorsque les constructeurs inférieurs au type courant ont besoin de paramètres supplémentaires. Par exemple :

public class Base
{
     public int SomeNumber { get; set; }

     public Base(int someNumber)
     {
         SomeNumber = someNumber;
     }
}

public class AlwaysThreeDerived : Base
{
    public AlwaysThreeDerived()
       : base(3)
    {
    }
}

Afin de construire un AlwaysThreeDerived il possède un constructeur sans paramètre. Cependant, l'objet Base ne le fait pas. Ainsi, afin de créer un constructeur sans paramètre, vous devez fournir un argument au constructeur de base, ce que vous pouvez faire avec l'attribut base mise en œuvre.

65voto

dasblinkenlight Points 264350

Oui, le constructeur de la classe de base sera appelé automatiquement. Vous n'avez pas besoin d'ajouter un appel explicite à base() quand il y a un constructeur sans arguments.

Vous pouvez facilement tester cela en imprimant l'âge du client après la construction ( lien vers ideone avec une démo ).

16voto

Science_Fiction Points 2051

Si vous n'aviez pas de constructeur sans paramètre par défaut, il serait nécessaire d'appeler le constructeur avec paramètres :

class Person
{
    public Person(string random)
    {

    }
}

class Customer : Person
{
    public Customer(string random) : base (random)
    {

    }
}

8voto

Stokely Points 405

En utilisant votre exemple, la réponse est : OUI . Le constructeur de base sera appelé pour vous et vous n'avez pas besoin d'en ajouter un.

Vous êtes seulement OBLIGÉ d'utiliser les appels "base(...)" dans votre classe dérivée si vous avez ajouté un constructeur avec des paramètres à votre classe de base, et n'avez pas ajouté un constructeur par défaut explicite.

Vous n'avez besoin de faire cet appel base(...) que si vous perturbez ou rompez la chaîne d'appel du constructeur implicite vers le constructeur de base de la classe dérivée. Cela se produit à la minute où vous ajoutez un constructeur non par défaut à votre classe de base.

En c#, avec des classes de base et des classes dérivées, certains appels aux constructeurs de la classe de base doivent toujours être effectués à partir de la classe dérivée, soit implicitement par le runtime, ou explicitement par vous. La plupart du temps, le runtime appellera le constructeur par défaut de la classe de base pour vous lorsque vous créez votre objet de classe dérivée, de sorte que vous n'avez pas besoin d'appeler "base()". Par défaut, une classe dérivée, lorsqu'elle est instanciée, appelle toujours IMPLICITEMENT le constructeur par défaut de la classe de base. C'est pourquoi, dans la plupart des cas, il n'est pas nécessaire d'ajouter "base()" au constructeur d'une classe dérivée. Une classe de base est toujours instanciée en premier à partir de la classe dérivée via un appel au constructeur par défaut de la classe de base, À MOINS que vous ne changiez ses constructeurs (voir ci-dessous). C# ne se soucie pas de savoir s'il s'agit d'un constructeur par défaut ou d'un constructeur non par défaut avec des paramètres. L'un d'eux doit être appelé dans la classe de base lorsque l'objet de la classe dérivée est créé.

C'est pourquoi vous pouvez omettre à la fois un appel à "base()" dans le constructeur de votre classe dérivée et un constructeur par défaut explicite dans toutes vos classes car il est appelé implicitement.

L'appel implicite au constructeur de la classe de base n'est vrai et effectué pour vous que si l'une des conditions suivantes est remplie. Si elle est vraie, vous n'avez PAS besoin d'appeler "base(...)" dans votre classe dérivée :

  1. Votre classe de base n'a pas de constructeurs explicites définis
  2. Votre classe de base a seulement un constructeur par défaut explicite défini
  3. Votre classe de base a un ou plusieurs constructeurs non par défaut définis avec des paramètres ET un constructeur par défaut explicite est défini.

Lorsque vous ajoutez soudainement un constructeur non par défaut avec un ou plusieurs paramètres et AUCUN constructeur par défaut, cela rompt la chaîne de création et d'appels du constructeur caché par défaut et vous DEVEZ ajouter "base()". Dans votre classe de base avec un constructeur par défaut, vous devez maintenant soit appeler ce constructeur explicitement depuis la classe dérivée en utilisant "base(...)", soit ajouter un constructeur par défaut explicitement dans la classe de base. Dans ce dernier cas, vous pouvez éviter les appels à "base()". Il est appelé implicitement.

Testons cela.....

// IMPLIED CONSTRUCTOR CALL TO THE BASE CLASS CALL WORKS NATURALLY HERE
class MyBaseClass0
{
// a default constructor added for you
}
class DerivedClass0 : MyBaseClass0
{
// an implied call to the base constructor is done for you
}

// THIS WORKS!!!
class MyBaseClass1
{
// a default constructor added for you
}
class DerivedClass1 : MyBaseClass1
{
    public DerivedClass1()
    {
      // Here the derived class default constructor is 
      // created explicitly but an implied call to the
      // base constructor is done for you
    }
}

// AND THIS WORKS!!!
class MyBaseClass2
{
// a default constructor added for you
}
class DerivedClass2 : MyBaseClass2
{
    public DerivedClass2() : base()
    {
    // "base()" is still optional here as implied call
    // to the base constructor is done for you
    }
}

// AND THIS WORKS!!!
class MyBaseClass3
{
// a default constructor added for you
}
class DerivedClass3 : MyBaseClass3
{
    public DerivedClass3(int x)// base not needed
    {
    // an implied call to the base constructor is still done for you
    }
}

// BECAUSE WE ADDED A NON-DEFAULT CONSTRUCTOR WITH
// NO EXPLICIT DEFAULT CONSTRUCTOR WE MUST USE "BASE(...)"

class MyBaseClass4
{
    // need explicit default constructor or must use "base()" now

    // non-default constructor added which breaks implicit call
    public MyBaseClass4(string y)
    {

    }
}
class DerivedClass4 : MyBaseClass4
{
    public DerivedClass4(int x) : base("hello")
    {
       // The implicit call to the default constructor is broken now
       // because we added a non-default constructor to base class.
       // Adding a "base()" call we have fulfilled the requirement
       // that some base constructor be called in the Base Class.
    }
}

// The IMPLIED default constructor call now works again
// because we added an explicit default constructor beside
// the non-default one we added. "base()" is not needed again.

class MyBaseClass5
{
    public MyBaseClass5()
    {
    }

    public MyBaseClass5(string y)
    {
    }
}
class DerivedClass5 : MyBaseClass5
{
    public DerivedClass5(string x)
    {
    }
}

7voto

Prakash Sharma Points 133

base() est appelé par défaut mais il peut être utilisé à d'autres fins telles que :

  1. La méthode base()` est utilisée pour passer la valeur à la construction de la classe parente ou à la méthode
  2. pour appeler le constructeur sans argument de la classe parente .

par exemple :

Cas 1 : si le parent a un constructeur paramétré mais pas de constructeur par défaut ou sans argument.

 class Person
 {

    private string FirstName;
    private string LastName;
    private string EmailAddress;
    private DateTime DateOfBirth;

    public Person(string firstName, string lastName, string emailAddress, DateTime dateOfBirth)
    {
        FirstName = firstName;
        LastName = lastName;
        EmailAddress = emailAddress;
        DateOfBirth = dateOfBirth;

    }
    }
class Employee : Person
{
    private double Salary { get; set; } = 0;

    public Employee(string firstName, string lastName, string emailAddress, DateTime dateOfBirth,double salary)
        :base(firstName,lastName,emailAddress,dateOfBirth)// used to pass value to parent constructor and it is mandatory if parent doesn't have the no-argument constructor.
    {
        Salary = salary;
    }
}

Cas 2 : lorsque le parent a plus d'un constructeur en plus de celui par défaut.

class Person
{

    private string FirstName;
    private string LastName;
    private string EmailAddress;
    private DateTime DateOfBirth;

    public Person()
    {
        // some important intialization's to be done  

    }

    public Person(string firstName, string lastName, string emailAddress, DateTime dateOfBirth)
    {
        FirstName = firstName;
        LastName = lastName;
        EmailAddress = emailAddress;
        DateOfBirth = dateOfBirth;

    }
    }
class PermanentEmployee : Person
{
    public double HRA { get; set; }
    public double DA { get; set; }
    public double Tax { get; set; }
    public double NetPay { get; set; }
    public double TotalPay { get; set; }

    public PermanentEmployee(double hRA, double dA, double tax, double netPay, double totalPay) : base();
    {
        HRA = hRA;
        DA = dA;
        Tax = tax;
        NetPay = netPay;
        TotalPay = totalPay;
    }
}

Ici, nous appelons un constructeur sans argument manuellement par base() pour effectuer quelques utilisations, mais il ne passe aucune valeur.

J'espère que cela vous aidera.

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