使用';这';在基构造函数中
本文关键字:构造函数 使用 | 更新日期: 2023-09-27 18:25:45
我正在处理一个涉及大量接口和继承的项目,这开始变得有点棘手,现在我遇到了一个问题。
我有一个抽象类State,它将Game对象作为构造函数参数。在我的Game类的构造函数中,它接受一个State。其思想是,当从抽象基类Game继承时,当调用基类的构造函数时,您会给它一个初始State对象。然而,这个State对象在你创建它的同一个游戏中。代码看起来像这样:
public class PushGame : ManiaGame
{
public PushGame() :
base(GamePlatform.Windows, new PlayState(this), 60)
{
}
}
然而,这不起作用。我只能假设,因为"this"关键字在构造函数开始执行之后才可用。显然,试图在基类的构造函数中使用它是行不通的。那么,我最好的解决方法是什么呢?我的计划B是从Game类的构造函数中删除State参数,然后在构造函数代码中设置状态。
有没有一种更简单、侵扰性更小的方法?
很明显,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){}
}
如果使用的State
实现依赖于具体的Game
类,那么我将在子Game
类(PushGame
)的构造函数内创建State
的新实例,并通过abstract
属性访问基类中的State
。
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) { }
}
来自C#语言规范
实例构造函数初始值设定项无法访问正在创建的实例。因此,在构造函数初始值设定项的参数表达式中引用它是编译时错误,参数表达式通过simple_name引用任何实例成员也是编译时错误。
即this
只能用于在构造函数初始化器的上下文中引用另一个构造函数,因为在构造完成之前,对当前对象实例的引用将不可用。
即this
在构造函数执行之前只能用作作用域关键字:
: this("ParameterForAnotherConstructor")
但它不能作为类实例的引用,因为它还没有完成的构建
: base(this) // Keyword this is not available in this context
很明显,我们也不能从构造函数初始值设定项调用任何实例方法
: base(GetThis()) // Object reference is required
为了解决OP的问题,考虑到PlayState
和ManiaGame
(或ManiaGame
的子类,如PushGame
)之间的双向耦合,对基本Mania
类的更改似乎是不可避免的。有很多模式可以用来解耦像这样的紧密依赖关系,比如依赖关系反转主体(即抽象类之间的耦合),或者观察者模式-(两个类中的一个引发事件或允许挂接回调(例如委托或Action
s),允许第二个类在没有它们之间的硬耦合的情况下"观察"状态变化。
还有一个类似的堆栈溢出问题,关键字"this"(Me)不可用,使用与您的建议类似的解决方法调用基构造函数。
您的设计是否区分了一个游戏(比如双陆棋)和一个正在进行的游戏(双陆棋游戏)?如果你试图将这两个概念混合在一起,那么我建议将它们分别建模。例如,双陆棋和双陆棋比赛。
我最近在尝试通过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();
}
}