使用';这';在基构造函数中

本文关键字:构造函数 使用 | 更新日期: 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的问题,考虑到PlayStateManiaGame(或ManiaGame的子类,如PushGame)之间的双向耦合,对基本Mania类的更改似乎是不可避免的。有很多模式可以用来解耦像这样的紧密依赖关系,比如依赖关系反转主体(即抽象类之间的耦合),或者观察者模式-(两个类中的一个引发事件或允许挂接回调(例如委托或Actions),允许第二个类在没有它们之间的硬耦合的情况下"观察"状态变化。

还有一个类似的堆栈溢出问题,关键字"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();
    }
}