多态和重载属性,它们是类层次结构中给定类型的“静态”

时间:2014-01-15 12:26:16

标签: c# polymorphism abstract-class

我必须通过发送命令与不同的硬件(但所有来自同一系列)进行交互。要存储命令,我之前使用的是枚举。然而,现在存在不同的hws并且取决于固件版本,除了基​​本命令之外还可以具有(i)新命令和/或(ii)一些基本命令的不同值。硬件实现了一个接口(我们称之为IHw)和一个基本抽象类(HwBase),它还提供了基本功能。

因此我想将枚举转换为具有虚拟属性的类,以便覆盖或添加功能。类似的东西:

public class CmdBase
{
    public virtual int SET_LED { get { return 0x10; } }
}
public class Cmd1 : CmdBase
{
    //override base command
    public override int SET_LED { get { return 0x20; } }
}
public class Cmd2 : CmdBase
{
    //add a functionality 
    public virtual int SET_LED_2 { get { return 0x30; } }
}

你认为这是正确的方法吗?如果是的话,这是使用这些命令的正确方法,以便每个hw访问自己的命令并具有某种多态性?我想也许仿制药可能有所帮助,但我不确定。我没有发布我尝试使用的尝试,而是发布了一种伪代码(这使得更容易理解),这种情况可以用于(但当然不可能)静态和静态方法可覆盖的属性:< / p>

public abstract class HwBase : IHw
{
    public virtual void SetLED()
    {
        // base implementation should send 0x10
        SendCommand(CmdBase.SET_LED);
    }
}
public class Hw1 : HwBase
{
    public override void SetLED()
    {
        // should send 0x20
        SendCommand(Cmd1.SET_LED);
    }
}
public class Hw2 : HwBase
{
    public virtual void SetLED2()
    {
        // should send 0x30
        SendCommand(Cmd2.SET_LED_2);
    }
}

修改

我所拥有的更“真实”的例子。这是HwBase中使用Cmd枚举中定义的命令的方法。

protected virtual bool SetFilter()
{
if (!SendCommand(new byte[] { Cmd.SET_HP_COEF_A1, (byte)(a1Conv >> 8), (byte)(a1Conv & 0xff), 0 }) ||
    !SendCommand(new byte[] { Cmd.SET_HP_COEF_B0, (byte)(b0Conv >> 8), (byte)(b0Conv & 0xff), 0 }) ||
    !SendCommand(new byte[] { Cmd.SET_HP_COEF_B1, (byte)(b1Conv >> 8), (byte)(b1Conv & 0xff), 0 }) ||
    !SendCommand(new byte[] { Cmd.SET_HP_COEF_D1, (byte)(d1Conv >> 8), (byte)(d1Conv & 0xff), 0 }) ||
    !SendCommand(new byte[] { Cmd.SET_HP_COEF_D2, (byte)(d2Conv >> 8), (byte)(d2Conv & 0xff), 0 }) ||
    !SendCommand(new byte[] { Cmd.SET_FILTER_MODE, 0, 0, 0}) )
        return false;

    return true;
}

然后在派生的Hw1中,根据固件版本,我可能需要与其他命令完全不同的过程。我希望除了Cmd之外还有这些命令,但仅对Hw1可见。现在它们位于另一个枚举CmdLegacy中,其中包含Cmd中定义的大多数命令(复制和粘贴)以及Cmd 中定义的一些相同命令,但具有不同的值和一些新命令(这样,如果您认为有数百个命令和几个hws,代码维护并不简单)。相反,我希望重用Cmd中定义的命令而不在CmdLegacy中复制和粘贴它们,而只是更改那些不同的命令并添加新的命令。

protected override bool SetFilter()
{
    if (isLegacyFirmware)
    {
        byte msg1;
        switch (filterValue)
        {
            default:
            case 0: msg1 = CmdLegacy.FILTER_CONST_758; break;
            case 1: msg1 = CmdLegacy.FILTER_CONST_1517; break;
            case 2: msg1 = CmdLegacy.FILTER_CONST_3034; break;
            case 3: msg1 = CmdLegacy.FILTER_CONST_6068; break;
            case 4: msg1 = CmdLegacy.FILTER_CONST_12136; break;
            case 5: msg1 = CmdLegacy.FILTER_CONST_24272; break;
        }

        byte msg2 = dataType == 0 ? CmdLegacy.UNFILTERED : CmdLegacy.FILTERED;

        return SendCommand(new byte[] { CmdLegacy.SET_FILTER_MODE, msg1, msg2, 0 });
    }
    return base.SetFilter();
}

2 个答案:

答案 0 :(得分:0)

您描述的对象模型如下所示:

public abstract class HwBase : IHw
{

    protected void SendCommand(int x)
    {
        // Send the value of 'x' to the appropriate device
    }

    public virtual void SetLED();

}

public class Hw1 : HwBase
{
    public override void SetLED()
    {
        // should send 0x20
        base.SendCommand(0x20);
    }
}

public class Hw2 : HwBase
{
    public virtual void SetLED()
    {
        // should send 0x30
        base.SendCommand(0x30);
    }
}

唯一的问号是你将如何确定哪一个是目标设备。

答案 1 :(得分:0)

我决定使用泛型,即使我仍然不确定它是否是正确/更优雅的方法。在问题中给出CmdBaseCmd1Cmd2,硬件类变为:

public abstract class HwBase<T> where T : CmdBase, new()
{
    protected static readonly T Commands = new T();
    public virtual void SetLED()
    {
        SendCommand(Commands.SET_LED); // 0x10
    }
}

public class Hw1 : HwBase<Cmd1>
{
    public override void SetLED()
    {
        SendCommand(Commands.SET_LED); // 0x20
    }
}
public class Hw2 : HwBase<Cmd2>
{
    public override void SetLED2()
    {
        SendCommand(Commands.SET_LED_2); // 0x30
    }
}