2010-07-26 2 views
2

Je suis en train de réaliser quelque chose comme ce qui suit:problème avec la conception en POO (appel membre virtuel dans le constructeur)

class Foo 
{ 
    public virtual int Number { get; set; } 

    public Foo(int n) 
    { 
     Number = n; //Virtual member call in constructor 
    } 

    public void Do() { 
     Console.WriteLine(Number); 
    } 

} 

class Bar : Foo 
{ 
    public override int Number 
    { 
     get 
     { 
      return x.Val; 
     } 
     set 
     { 
      x.Val = value; 
     } 
    } 

    Bar(int n) : base(n) 
    { 
     X x = new X(); 
     x.Val = n; 
    } 

    public void F() { 
     x.Something(); //changes x.Val 
    } 
} 

La raison pour laquelle je fais cela est parce que je dois propager l'appel à Do lorsqu'il est appelé à partir d'une variable de type Bar.

Maintenant, je peux avoir des objets qui soit hériter de Foo ou Bar, ainsi Number doit être la façon dont il est maintenant, à savoir exposer directement la propriété Val de x. Ceci est parce que je dois permettre le code suivant:

Bar b = new Bar(5); 
b.F(); //changes the value of Val in x 
b.Do(); //Needs to print the correct, modified value 

Le problème ici est évidemment Foo, lors de l'attribution n-Number (Virtual member call in constructor) depuis x de la sous-classe n'aurait pas encore été initialisée.


Selon vous, quelle est la meilleure façon de structurer une telle conception?

Je ne peux pas utiliser ce code actuel parce que je fais appel un membre virtuel du constructeur, ce qui provoque l'exception Object Reference not set to an Instance of an Object depuis x dans Number de Bar n'aurait pas encore été initialisé.

+0

Il est une mauvaise pratique d'appeler des méthodes non-finales de super constructeurs de classe. – Zaki

+0

Oui, c'est pourquoi je demande un design alternatif –

Répondre

0

Ma citation préférée:

composition Faveur sur l'héritage

Je séparer les données sous-jacentes des opérations:

interface IMyNumber 
{ 
    int Number { get; set; } 

    void Something(); 
} 

class MyNumber : IMyNumber 
{ 
    public int Number { get; set; } 

    public MyNumber(int n) 
    { 
     Number = n; 
    } 

    void Something() {... } 
} 

class MyBoxedNumber : IMyNumber 
{ 
    int Number { get { ... } set {... } } 

    void Something() {... } 
} 

class Bar 
{ 
    private IMyNumber_foo; 

    Bar(IMyNumber foo) 
    { 
     _foo = foo; 
    } 

    public void F() { 
     _foo.Something(); //changes x.Val 
    } 

    public void Do() { 
     Console.WriteLine(...) 
    } 
}