我正在开发一个涉及大量接口和继承的项目,这些项目开始变得有点棘手,现在我遇到了一个问题。
我有一个抽象类State,它将Game对象作为构造函数参数。在我的Game类的构造函数中,它接受一个State。这个想法是,当从抽象基类Game类继承时,在调用基类的构造函数时,你给它一个初始的State对象。但是,这个State对象与您正在创建它的游戏相同。代码如下所示:
public class PushGame : ManiaGame
{
public PushGame() :
base(GamePlatform.Windows, new PlayState(this), 60)
{
}
}
然而,这不起作用。我只能假设因为'this'关键字在构造函数开始执行之后才可用。试图在基类的构造函数中使用它显然不起作用。那么对我来说最好的解决方法是什么呢?我的计划B是从Game类的构造函数中删除State参数,然后在构造函数代码中设置状态。
是否有更容易,更少侵入性的方法?
答案 0 :(得分:8)
显然,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){}
}
答案 1 :(得分:1)
实例构造函数初始值设定项无法访问正在创建的实例。因此,在构造函数初始化程序的参数表达式中引用它是一个编译时错误,因为参数表达式通过simple_name引用任何实例成员的编译时错误。
即。 this
只能用于在构造函数初始值设定项的上下文中引用另一个构造函数,因为在构造完成之前,对当前对象实例的引用将不可用。
即。 this
只能在构造函数执行之前用作作用域关键字:
: this("ParameterForAnotherConstructor")
但是它不能作为类实例的引用,因为它还没有完成构造
: base(this) // Keyword this is not available in this context
显然我们不能从构造函数初始化程序中调用任何实例方法
: base(GetThis()) // Object reference is required
要解决OP的问题,考虑到Mania
和PlayState
(或ManiaGame
的子类之间的双向耦合,对基类ManiaGame
类的更改似乎是不可避免的,例如PushGame
)。有许多模式可用于解耦这样的紧密依赖,例如Dependency Inversion Principal(即抽象类之间的耦合)或Observer模式 - (两个类之一引发事件或允许回调挂钩(例如,委托或Action
s),允许第二类“观察”状态变化,而不需要它们之间的硬耦合。
有一个类似的Stack Overflow问题, Keyword 'this' (Me) is not available calling the base constructor ,其解决方法类似于您的建议。
答案 2 :(得分:1)
如果使用的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 :(得分:0)
您的设计是否区分游戏(步步高)和正在进行的游戏(步步高游戏)?如果你想尝试混合这两个概念,那么我建议你分别对它们进行建模。例如,西洋双陆棋和西洋双陆棋。
答案 4 :(得分:0)
当尝试通过this
将已实现接口的具体实例传递给基本构造函数时,我遇到了这个问题。
要解决此问题,我只是在基类上实现了一个抽象方法,该方法获取了我要查找的实例:
public abstract class BaseClass
{
...
protected abstract IMyInterface GetInterface();
...
}
public class DerivedClass : BaseClass, IMyInterface
{
...
protected override IMyInterface GetInterface()
{
return this;
}
...
}
然后在我的基类代码中,您可以使用GetInterface
(或所需的任何类型)来获取实例:
public abstract class BaseClass
{
public void Foo()
{
GetInterface().DoSomething();
}
}