Nouveau sur OOP et je suis confus par la façon dont les constructeurs de classes dérivées fonctionnent lors de l'héritage d'une classe de base en C #.
D'abord la classe de base:
class BaseClass
{
private string BaseOutput = null;
public BaseClass(string BaseString)
{
BaseOutput = BaseString;
}
public virtual void PrintLine()
{
Console.WriteLine(BaseOutput);
}
}
Voici la classe dérivée:
class SubClass : BaseClass
{
private string SubOutput = null;
public SubClass(string BaseString, string SubString) : base(BaseString)
{
SubOutput = SubString;
}
public override void PrintLine()
{
Console.WriteLine(SubOutput);
}
}
Enfin, l'essentiel du programme:
class Program
{
static void Main(string[] args)
{
BaseClass theBase = new BaseClass("Text for BaseClass");
SubClass theSub = new SubClass("2nd param", "Text for SubClass");
theBase.PrintLine();
theSub.PrintLine();
Console.ReadKey();
}
}
Ce que je ne comprends pas, c'est pourquoi, lorsque j'appelle le constructeur de la classe dérivée, je dois également passer le paramètre dont la classe de base a besoin. Le champ BaseOutput de la classe dérivée ne doit-il pas simplement rester défini sur null si aucune valeur ne lui est affectée? Pourquoi quelque chose comme ce travail ne peut-il pas:
public SubClass(string SubString) : base(BaseString)
De plus, lors de l'appel du constructeur dans cette classe dérivée, le premier paramètre doit être nommé de la même manière que celui de la classe de base, sinon il génère une erreur. Si je devais définir une nouvelle variable de chaîne appelée AnotherString dans la classe dérivée, pourquoi cela ne fonctionnerait-il pas:
public SubClass(string AnotherString, string SubString) : base(BaseString)
Enfin, lorsque vous faites cela de la bonne façon et que vous tapez ceci ...
public SubClass(string BaseString, string SubString) : base(BaseString)
... à quoi sert le premier paramètre du constructeur SubClass? Il n'est assigné ou utilisé dans aucune méthode pour ma classe dérivée. Pourquoi dois-je même le mettre là-bas?
Quant à savoir pourquoi vous ne pouvez pas faire:
public SubClass(string SubString) : base(BaseString)
Que serait BaseString
?
Vous pourriez faire:
public SubClass(string SubString) : base("SomeFixedString")
ou
public SubClass(string SubString) : base(SubString)
Mais si vous voulez passer une chaîne au paramètre du constructeur de la classe de base et en avoir une autre, vous devrez accepter deux paramètres.
Quant à garder le même nom, vous ne le faites pas. Vous pourriez faire:
public SubClass(string AnotherString, string SubString) : base(AnotherString)
Quant à la dernière question, le premier paramètre ne fait rien, il est passé au constructeur de la classe de base. Vous pouvez l'utiliser pour autre chose si vous le souhaitez.
Si vous souhaitez donner à la classe dérivée la possibilité de NE PAS définir la BaseString, vous devez fournir un constructeur par défaut dans la classe de base comme ceci:
public BaseClass()
{
}
Maintenant, dans la classe dérivée, vous pouvez appeler le constructeur sans arguments dans la classe de base comme ceci:
public SubClass(string AnotherString)
: base()
{
// base() => explicit call to default construct in the base class.
// Do something else
}
Cela fournit de bonnes pratiques d'ingénierie logicielle: si vous souhaitez donner la possibilité de ne pas définir la chaîne de la classe de base, faites-le dans la classe de base. D'autres 'hacks' comme passer null comme argument au constructeur de base ne servent qu'à bricoler les internes de la classe de base d'une manière qui ne devrait pas être effectuée à partir des sous-classes.
public SubClass(string BaseString, string SubString) : base(BaseString)
Ce constructeur de la classe dérivée indique que lorsque vous recevez deux arguments BaseString
et SubString
, appelez le constructeur de la classe de base avec BaseString
.
Ainsi, faire
public SubClass(string a, string b) : base(BaseString)
ne fonctionne pas, car vous lui dites d'appeler le constructeur de la classe de base avec BaseString
mais il n'y a pas d'argument appelé BaseString
.
Si vous souhaitez instancier la classe dérivée sans passer une chaîne au constructeur de la classe de base, la classe de base a besoin d'un constructeur par défaut:
public BaseClass() { }
Si vous souhaitez initialiser BaseString
avec la valeur par défaut, transmettez cette valeur au constructeur de la classe de base (vous n'avez donc pas à transmettre ce paramètre au constructeur de la classe dérivée)
public SubClass(string SubString) : base(null)
Ou définissez un constructeur sans paramètre dans la classe de base.
Également sur la dénomination des paramètres - peu importe le nom du paramètre, que vous transmettez au constructeur dérivé. La seule chose qui compte est une valeur que vous transmettez au constructeur de base.
public SubClass(string AnotherString, string SubString) : base(AnotherString)