如何明确继承的实例变量

本文关键字:实例 变量 继承 何明确 | 更新日期: 2023-09-27 18:20:44

我一直在处理一些抽象类,感觉有些不对劲,但我不知道该怎么办。下面是一个简单的例子来解释我的问题:

public abstract class Data
{
    protected Boolean _Connected = false;
    public abstract void Connect();
    public abstract void Disconnect();
    public Boolean Connected
    {
        get { return _Connected; }
    }
}
public class SqlServerData : Data
{
    public override void Connect()
    {
        // code to connect to sql server
        _Connected = true;
    }
    public override void Disconnect()
    {
        if (_Connected)
        {
            // code to disconnect from sql server
            _Connected = false;
        }
    }    
}

我在设计上有几个问题。

  1. 此设计中没有任何内容强制Data的新实现对_connected实例变量执行任何操作。如果使用Data类的其他类依赖Connected属性,则该属性可能不准确。

  2. 这可能会让刚接触此代码的人感到困惑。这个示例非常简单,但如果抽象类中有更多的实例变量,SqlServerData类中有其他实例变量,那么就更难知道变量是在哪里定义的。

所以我的问题是,这是否应该重构?如果是,如何重构?

如何明确继承的实例变量

在基类中实现状态机(连接或未连接,以及这些状态之间的转换),因此派生类不必担心这一部分。为实际功能提供受保护的方法,因此派生类可以很容易地填补"漏洞":

public abstract class Data
{
    private bool connected;
    public bool Connected
    {
        get { return connected; }
    }
    public void Connect()
    {
        OnConnect();
        connected = true;
    }
    public void Disconnect()
    {
        if (connected)
        {
            OnDisconnect();
            connected = false;
        }
    }
    protected virtual void OnConnect() { }
    protected virtual void OnDisconnect() { }
}

public class SqlServerData : Data
{
    protected override void OnConnect()
    {
        // code to connect to sql server
    }
    protected override void OnDisconnect()
    {
        // code to disconnect from sql server
    }    
}

问题是,您希望管理_connected标志的逻辑在所有子类之间共享,但仍然保留每个子类在实际调用Connect()和Disconnect()时提供自己实现的能力。为此,我建议使用所谓的模板方法模式,这样抽象基类仍然可以保留对方法中使用的逻辑的一些控制。它的工作方式非常简单,只需将类的结构类似于以下内容:

public void Connect() {
   if(!_connected) {
      ExecuteConnect();
      _connected = true;
   }
}
public void Disconnect() { 
   if(_connected) {
      ExecuteDisconnect();
      _connected = false;
   }
 }
 protected abstract void ExecuteConnect();
 protected abstract void ExecuteDisconnect();

现在,在基类中,您可以覆盖Execute*方法(我相信命名约定可以改进),这样您就可以为连接和断开连接提供新的实现,同时仍然管理对通用算法的控制。

我宁愿使属性Connected抽象并提交受保护的字段。

受保护田地的缺点是,基地和孩子们必须以一致的方式使用它,从而使他们更加紧密地结合在一起。

但是,拥有受保护的字段可能会为您节省一些简单的代码行。这取决于实际问题,但通常我宁愿多写几行代码,然后引入耦合。