Использование 'this' в базовом конструкторе?

Я работаю над проектом, который включает в себя много интерфейсов и наследования, которые начинают немного сложнее, и теперь я столкнулся с проблемой.

У меня есть абстрактное состояние класса, которое принимает объект Game в качестве аргумента конструктора. В моем конструкторе класса Game он принимает состояние. Идея состоит в том, что при наследовании от абстрактного базового класса Game при вызове конструктора базового класса вы даете ему исходный объект State. Однако этот объект State принимает в той же игре, в которой вы ее создаете. Код выглядит следующим образом:

public class PushGame : ManiaGame
{
     public PushGame() :
          base(GamePlatform.Windows, new PlayState(this), 60)
     {
     }
}

Однако это не работает. Я могу предположить только потому, что ключевое слово 'this' не используется до тех пор, пока конструктор не начнет выполнение. Попытка использовать его в конструкторе базового класса, по-видимому, не работает. Итак, каково было бы мое лучшее обходное решение для этого? Мой план B состоит в том, чтобы просто удалить аргумент State из конструктора класса Game и просто установить состояние внутри кода конструктора впоследствии.

Есть ли более простой, менее навязчивый способ сделать это?

Ответы

Ответ 1

Очевидно, что класс ManiaGame всегда использует объекты типа PlayState, поэтому вы можете перемещать создание на уровне ManiaGame:

public class PushGame : ManiaGame
{
     public PushGame() : base()
     {
     }

}

public class ManiaGame
{
    PlayState ps;   
    public ManiaGame() {
        ps = new PlayState(this);
    }
}

Если вам нужны более конкретные классы PlayState..

public class PushGame : ManiaGame
{
     public PushGame() : base()
     {
     }
     protected override PlayState CreatePlayState()
     {
        return new PushGamePlayState(this);
     }
}

public class ManiaGame
{
    PlayState ps;   
    public ManiaGame() {
          ps = CreatePlayState();
    }
    protected virtual PlayState CreatePlayState()
    {
        return new PlayState(this);
    }
}

public class PlayState
{
   public PlayState(ManiaGame mg) {}
}


public class PushGamePlayState : PlayState
{
   public PushGamePlayState(ManiaGame mg) : base(mg){}
}

Ответ 2

Если используемая реализация State зависит от конкретного класса Game, я бы создал новый экземпляр State внутри конструктора дочернего класса Game (PushGame) и получил доступ к State в базовом классе через свойство abstract.

public class PushGame : ManiaGame
{
    private readonly PlayState gamePlayState;

    public PushGame() : base()
    {
        gamePlayState = new PlayState(this);
    }

    protected override State GamePlayState
    {
        get { return gamePlayState; }
    }
}

public abstract class ManiaGame
{
    protected abstract State GamePlayState { get; }
}

public class State
{
    public State(ManiaGame mg) { }
}


public class PlayState : State
{
    public PlayState(ManiaGame mg) : base(mg) { }
}

Ответ 3

Похоже, что 'this' может использоваться только для ссылки на другой конструктор в этом контексте.

То есть, это используется как ключевое слово определения перед выполнением конструктора:

    : this("ParameterForAnotherConstructor")

Но он не доступен в качестве обычной ссылки на экземпляр класса,

    : base(this) // Keyword this is not available in this context

И, очевидно, он не может вызвать какие-либо методы экземпляра либо

    : base(GetThis()) // Object reference is required

Существует аналогичный вопрос, Ключевое слово 'this' (Me) недоступно, вызывая базовый конструктор с обходным решением, аналогичным вашему предложению.

Ответ 4

Отличается ли ваш дизайн между игрой (скажем, в нарды) и игрой (игра в нарды)? Если вы попытаетесь смешать эти две концепции, я бы предложил их моделировать отдельно. Например, Backgammon и BackgammonContest.