2010-10-06 3 views
18

Je sais qu'il n'est pas possible d'hériter de constructeurs en C#, mais il y a probablement un moyen de faire ce que je veux faire.C#: constructeurs héritiers

J'ai une classe de base qui est héritée par beaucoup d'autres classes, et elle a une méthode Init qui effectue une initialisation en prenant 1 paramètre. Toutes les autres héritant des classes ont également besoin de cette initialisation, mais je avais besoin de créer des constructeurs distincts pour tous ceux qui voudraient comme ceci:

public Constructor(Parameter p) { 
    base.Init(p); 
} 

qui viole totalement les principes SECS! Comment puis-je initialiser toutes les choses nécessaires sans créer des douzaines de constructeurs?

+2

Pire que de violer les principes DRY est en violation du principe invariant. "Init" comme le nom d'une méthode est généralement un signe fort que les objets existent inutilement dans des états invalides où la seule chose pour laquelle ils sont bons cause des bogues. –

+1

C# ne suit pas vraiment DRY du tout. Cela peut être gênant mais ... honnêtement, vous ne pouvez pas me dire que vous n'êtes pas fatigué de taper 'public',' protected', et 'private' encore et encore et encore? –

+1

@ SlippD.Thompson: C'est un autre domaine où C++ est en fait * moins * verbeux que des langages plus faciles ... Le précédent que je viens de voir concernait l'exposition de constructeurs de base dans une classe dérivée. –

Répondre

47

Vous n'avez pas besoin de créer des charges de constructeurs, toutes avec le même code; vous créez un seul, mais les classes dérivées appellent le constructeur de base:

public class Base 
{ 
    public Base(Parameter p) 
    { 
     Init(p) 
    } 

    Init(Parameter p) 
    { 
     // common initialisation code 
    } 
} 

public class Derived : Base 
{ 
    public Derived(Parameter p) : base(p) 
    { 

    } 
} 
+1

C'est ce dont j'ai besoin. Bien que je doive créer des constructeurs pour les classes qui n'en ont pas, je n'aurai pas à répéter le code. – Alex

+1

pourquoi le vote en baisse? –

+1

Je souhaite que C# ait quelque chose comme les constructeurs hérités de C++, il est toujours ennuyeux d'appeler tous les constructeurs de base –

7

Modifier la fonction init est le constructeur de la classe de base, puis appeler des objets hérités comme celui-ci:

public InheritedObject(Parameter p) : base(p) 
{ 
} 

Le constructeur de base sera appelée avant tout code dans le constructeur exécute lui-même .

2

Quelque chose comme ça?

public Constructor(Parameter p) : base(p) { 

} 

Et la classe de base:

public Base(Parameter p) 
{ 
    Init(p); 
} 

Vous pouvez même marquer votre méthode Init comme virtuelle, de sorte que vous pouvez faire un peu override doux dans vos autres classes, le cas échéant! ;)

public virtual void Init() { } 

et dans vos autres classes:

public override void Init() { base.Init(); //Do other stuff } 
+2

Bien que vous deviez être très prudent en appelant une méthode virtuelle d'un constructeur - le constructeur de la sous-classe ne se serait pas exécuté lorsque la méthode surchargée est appelée par la superclasse, donc les variables membres n'auraient pas été initialisées. – thecoop

+0

true :) mais vous trouverez ce problème très rapide .. – Arcturus

+1

La méthode init virtuelle semble inutile, cependant. Normalement vous devriez éviter de travailler dans les constructeurs, et ne les utiliser que pour l'initialisation, et si c'est seulement l'initialisation, alors pourquoi ne pas simplement utiliser le constructeur? – AHM

5

La seule façon de ne pas répéter l'appel base.Init est d'appeler à la place le constructeur de base

class Base 
{ 
    public Base(Parameter p) 
    { 
    this.Init(p) 
    } 

    private void Init(Parameter p) 
    { 
     ... 
    } 
} 

class Inherited : Base 
{ 
    public Inherited(Parameter p) 
    : base(p) 
    { 
     // other constructor logic, but Init is already called. 
    } 
} 
3

Vous ne pouvez pas hériter constructeurs mais vous pouvez les appeler à partir des constructeurs de vos enfants dérivés. Si vous rendez le constructeur par défaut des classes de base private, il vous forcera à sélectionner un constructeur de base chaque fois que vous créerez une classe dérivée.

class A 
{ 
    protected A(int x) 
    { 

    } 
} 
class B : A 
{ 
    B(int x) 
     : base(x) 
    { 

    } 
} 
Questions connexes