跨界面合同

时间:2014-01-16 14:49:13

标签: c# oop interface documentation design-by-contract

我认为接口不仅是一组成员,而且还是一个“契约”,它强制实现保持接口文档中指定的限制。例如:

interface IDevice
{
    bool IsActive { get; }

    int Address { get; }

    /// <summary>
    /// Raised when (IsActive == false)
    /// and device was activated
    /// </summary>
    event Action Activated;

    /// <summary>
    /// Raised when (IsActive == true)
    /// and device was deactivated
    /// </summary>
    event Action Deactivated;

    /// <summary>
    /// Raised when (IsActive == false)
    /// and Address was changed
    /// </summary>
    event Action<int> AddressChanged;
}

此外,我的用户对激活/停用过程不感兴趣,但想知道Address何时会发生变化,因此,在ISP的带领下,我创建了一个新界面:

interface IAddressee
{
    int Address { get; }

    /// <summary>
    /// Raised when Address was changed
    /// </summary>
    event Action<int> AddressChanged;
}

现在IDevice看起来像:

interface IDevice : IAddressee
{
    bool IsActive { get; }

    /// <summary>
    /// Raised when (IsActive == false)
    /// and device was activated
    /// </summary>
    event Action Activated;

    /// <summary>
    /// Raised when (IsActive == true)
    /// and device was deactivated
    /// </summary>
    event Action Deactivated;
}

如您所见,IDevice的合同已经失去了一个条件:AddressChanged事件只有在设备处于非活动状态时才会引发(IsActive == false)。

我无法在IAddressee接口中记录它,因为它不依赖于IDevice,并且可以存在非设备实现。

这种情况是否正常?你会采取什么措施来强制IDevice实现纠正行为?

我是合约概念的新手,所以请消除我的幻想和怀疑

1 个答案:

答案 0 :(得分:1)

在这种情况下,抽象条件就可以了。它们表达的内容可能取决于顶级课程中没有的信息。稍后以适合特定后代的方式实施该条件。在你的例子中

interface IAddressee
{
    int Address { get; }

   /// <summary>
   /// Can Address be changed?
   /// </summary>
   bool IsAddessChangeable { get; };

    /// <summary>
    /// Raised when (IsAddessChangeable == true)
    /// and Address was changed
    /// </summary>
    event Action<int> AddressChanged;
}

在实现IDevice的类中,查询IsAddessChangeable将在其他类中返回IsActive == false - 值取决于所需的语义。