Использование '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.