如何清除继承的实例变量?

时间:2012-01-19 17:23:52

标签: c# oop

我一直在处理一些抽象的课程,感觉不舒服,但我不知道该怎么做。这是一个简单的例子来解释我的问题:

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类中有其他实例变量,则更难以了解变量的定义位置。

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

3 个答案:

答案 0 :(得分:6)

在基类中实现状态机(已连接或未连接,以及这些状态之间的转换),因此派生类不必担心此部分。为实际功能提供受保护的方法,因此派生类可以轻松填写​​“漏洞”:

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
    }    
}

答案 1 :(得分:3)

问题在于您希望逻辑管理 _connected 标志以在所有子类之间共享,但仍保留每个子类提供其实际调用时所发生情况的实现的能力连接()和断开连接()。为此,我建议使用所谓的Template Method Pattern,这样抽象基类仍然可以保留对方法中使用的逻辑的一些控制。它的工作方式非常简单,只需构建类似于此的类:

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 *方法(我确定可以改进命名约定),这样你就可以为连接和断开连接提供新的实现,同时仍然可以管理对通用算法的控制。

答案 2 :(得分:0)

我宁愿将属性Connected抽象化并省略受保护的字段。

受保护领域的缺点是基地和儿童必须以一致的方式使用它,从而将它们结合在一起。

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