如何明确继承的实例变量
本文关键字:实例 变量 继承 何明确 | 更新日期: 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;
}
}
}
我在设计上有几个问题。
此设计中没有任何内容强制Data的新实现对_connected实例变量执行任何操作。如果使用Data类的其他类依赖Connected属性,则该属性可能不准确。
这可能会让刚接触此代码的人感到困惑。这个示例非常简单,但如果抽象类中有更多的实例变量,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
抽象并提交受保护的字段。
受保护田地的缺点是,基地和孩子们必须以一致的方式使用它,从而使他们更加紧密地结合在一起。
但是,拥有受保护的字段可能会为您节省一些简单的代码行。这取决于实际问题,但通常我宁愿多写几行代码,然后引入耦合。