Проблема с дизайном в ООП (вызов виртуального члена в конструкторе) - PullRequest
2 голосов
/ 26 июля 2010

Я пытаюсь добиться чего-то вроде следующего:

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
    }
}

Причина, по которой я это делаю, заключается в том, что мне нужно распространить вызов на Do при вызове из переменной типа Bar.

Теперь у меня могут быть объекты, которые наследуются от Foo или Bar, таким образом, Number должен быть таким, какой он есть сейчас, то есть напрямую выставлять свойство Val x,Это потому, что мне нужно разрешить следующий код:

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

Проблема, очевидно, здесь в Foo, когда присваивается n для Number (Virtual member call in constructor), поскольку x изподкласс еще не был бы инициализирован.


Как вы думаете, что является лучшим способом структурировать такой дизайн?

Я не могу использовать этот текущий код, потому что я вызываю виртуальный член из конструктора, что вызывает исключение Object Reference not set to an Instance of an Object, поскольку x в Number из Bar еще не было бы инициализировано.

1 Ответ

0 голосов
/ 26 июля 2010

Моя любимая цитата:

Пользу композиции по наследованию

Я бы отделил базовые данные от операций:

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(...)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...