如何在继承接口时将实现添加到接口代码协定

本文关键字:接口 添加 代码 实现 继承 | 更新日期: 2023-09-27 17:55:47

我的例子是继承基本接口的接口需要添加作为其附加字段结果的后置条件的情况 - 当我决定将 IInitialise 接口作为继承自此接口的接口时,就会发生该示例总是希望将前/后条件添加到 Initialise 方法中。

我可以看到问题是由于抽象实现无法相互避免(由于拦截或重写器)。

    [ContractClass(typeof(IInitialiseContract))]
    public   interface IInitialise
    {
        bool IsInitialised { get; }
        void Initialise();
    }
    [ContractClassFor(typeof(IInitialise))]
    public abstract class IInitialiseContract : IInitialise
    {
        public bool IsInitialised
        {
            get { return default(bool); }
        }
        public void Initialise()
        {
            Contract.Ensures(IsInitialised == true);
        }
    }

然后后来我最终得到了以下界面

  [ContractClass(typeof(IEnginecontract))]
    public interface IEngine : IInitialise 
    {
        ICommandManager CommandManager { get; }
        IDictionary<int, IEntity> World { get; } 
    }
    [ContractClassFor(typeof(IEngine))]
    public abstract class IEnginecontract : IEngine
    {
        public ICommandManager CommandManager
        {
            get
            {
                Contract.Ensures(Contract.Result<ICommandManager>() != null);
                return default(ICommandManager);
            }
        }
        public IDictionary<int, IEntity> World
        {
            get
            {
                Contract.Ensures(Contract.Result<IDictionary<int, IEntity>>() != null);
                return default(IDictionary<int, IEntity>);
            }
        }
        public bool IsInitialised
        {
            get { return default(bool); }
        }
        public void Initialise()
        {
            // I would like to put my pre and post conditions here but 
            // cannot because it is implemented in the base interfaces contract.
        }
    }

我到了这里,我想不出一种很好的干净方法来向 Initialise() 添加条件。

编辑2:如果我在这种方法中提出了要求,我会得到这样的错误

警告 1 协定类 IEngine 无法为方法 IInitialise 定义协定。初始化,因为它的原始定义不在 IEngine 类型中。改为在类型 II 上定义协定。 .cs

有什么想法吗?

如何在继承接口时将实现添加到接口代码协定

任何来自您为其编写合约的接口以外的接口的方法都应标记为abstract 。这些方法的协定将自动继承,您无法更改它们(否则这会更改基本接口的含义,这没有意义)。

所以你应该有你的基本接口和它的合约:

[ContractClass(typeof(IInitialiseContract))]
public interface IInitialise
{
    bool IsInitialised { get; }
    void Initialise();
}
[ContractClassFor(typeof(IInitialise))]
public abstract class IInitialiseContract : IInitialise
{
    public bool IsInitialised
    {
        get { return default(bool); }
    }
    public void Initialise()
    {
        Contract.Ensures(IsInitialised == true);
    }
}

以及您的派生接口及其合约(注意抽象继承的):

[ContractClass(typeof(IEnginecontract))]
public interface IEngine : IInitialise 
{
    ICommandManager CommandManager { get; }
    IDictionary<int, IEntity> World { get; } 
}
[ContractClassFor(typeof(IEngine))]
public abstract class IEnginecontract : IEngine
{
    public ICommandManager CommandManager
    {
        get
        {
            Contract.Ensures(Contract.Result<ICommandManager>() != null);
            return default(ICommandManager);
        }
    }
    public IDictionary<int, IEntity> World
    {
        get
        {
            Contract.Ensures(Contract.Result<IDictionary<int, IEntity>>() != null);
            return default(IDictionary<int, IEntity>);
        }
    }
    public abstract bool IsInitialised {get;}
    public abstract void Initialise();
}

我认为这是不可能的。我广泛使用代码协定,据我所知 - 我记得我自己尝试过这样的东西 - 你的派生接口的代码契约必须再次包含所有条件,它不能继承它们。