定义构造函数签名的接口?

筅森魡賤 提交于 2020-02-26 16:08:29

这是我第一次碰到这个问题,这很奇怪,但是:

如何在C#接口中定义构造函数?

编辑
有些人想要一个例子(这是一个空闲时间项目,所以是的,这是一个游戏)

IDrawable
+更新
+绘制

为了能够更新(检查屏幕边缘等)并绘制自身,它将始终需要GraphicsDeviceManager 。 所以我想确保对象有引用它。 这将属于构造函数。

现在我写下来了,我认为我在这里实现的是IObservableGraphicsDeviceManager应该使用IDrawable ......似乎要么我没有得到XNA框架,要么框架没有考虑得很好。

编辑
关于我在接口上下文中对构造函数的定义似乎有些混乱。 实际上不能实例化接口,因此不需要构造函数。 我想要定义的是构造函数的签名。 正如接口可以定义某个方法的签名,接口可以定义构造函数的签名。


#1楼

如果可以在接口中定义构造函数,那将非常有用。

鉴于接口是必须以指定方式使用的合同。 对于某些场景,以下方法可能是一种可行的替代方法:

public interface IFoo {

    /// <summary>
    /// Initialize foo.
    /// </summary>
    /// <remarks>
    /// Classes that implement this interface must invoke this method from
    /// each of their constructors.
    /// </remarks>
    /// <exception cref="InvalidOperationException">
    /// Thrown when instance has already been initialized.
    /// </exception>
    void Initialize(int a);

}

public class ConcreteFoo : IFoo {

    private bool _init = false;

    public int b;

    // Obviously in this case a default value could be used for the
    // constructor argument; using overloads for purpose of example

    public ConcreteFoo() {
        Initialize(42);
    }

    public ConcreteFoo(int a) {
        Initialize(a);
    }

    public void Initialize(int a) {
        if (_init)
            throw new InvalidOperationException();
        _init = true;

        b = a;
    }

}

#2楼

通用工厂方法似乎仍然是理想的。 您会知道工厂需要一个参数,而这些参数会被传递给正在实例化的对象的构造函数。

注意,这只是语法验证的伪代码,可能有一个运行时警告我在这里缺少:

public interface IDrawableFactory
{
    TDrawable GetDrawingObject<TDrawable>(GraphicsDeviceManager graphicsDeviceManager) 
              where TDrawable: class, IDrawable, new();
}

public class DrawableFactory : IDrawableFactory
{
    public TDrawable GetDrawingObject<TDrawable>(GraphicsDeviceManager graphicsDeviceManager) 
                     where TDrawable : class, IDrawable, new()
    {
        return (TDrawable) Activator
                .CreateInstance(typeof(TDrawable), 
                                graphicsDeviceManager);
    }

}

public class Draw : IDrawable
{
 //stub
}

public class Update : IDrawable {
    private readonly GraphicsDeviceManager _graphicsDeviceManager;

    public Update() { throw new NotImplementedException(); }

    public Update(GraphicsDeviceManager graphicsDeviceManager)
    {
        _graphicsDeviceManager = graphicsDeviceManager;
    }
}

public interface IDrawable
{
    //stub
}
public class GraphicsDeviceManager
{
    //stub
}

可能的用法示例:

    public void DoSomething()
    {
        var myUpdateObject = GetDrawingObject<Update>(new GraphicsDeviceManager());
        var myDrawObject = GetDrawingObject<Draw>(null);
    }

当然,您只需要通过工厂的创建实例来保证您始终拥有适当的初始化对象。 也许使用像AutoFac这样的依赖注入框架是有意义的; Update()可以“询问”IoC容器中的新GraphicsDeviceManager对象。


#3楼

我发现解决这个问题的一种方法是将建筑分隔成一个单独的工厂。 例如,我有一个名为IQueueItem的抽象类,我需要一种方法将该对象转换为另一个对象(CloudQueueMessage)。 所以在IQueueItem界面上我有 -

public interface IQueueItem
{
    CloudQueueMessage ToMessage();
}

现在,我还需要一种方法让我的实际队列类将CloudQueueMessage转换回IQueueItem - 即需要静态构造,如IQueueItem objMessage = ItemType.FromMessage。 相反,我定义了另一个接口IQueueFactory -

public interface IQueueItemFactory<T> where T : IQueueItem
{
    T FromMessage(CloudQueueMessage objMessage);
}

现在我终于可以在没有new()约束的情况下编写我的通用队列类,在我看来这是主要问题。

public class AzureQueue<T> where T : IQueueItem
{
    private IQueueItemFactory<T> _objFactory;
    public AzureQueue(IQueueItemFactory<T> objItemFactory)
    {
        _objFactory = objItemFactory;
    }


    public T GetNextItem(TimeSpan tsLease)
    {
        CloudQueueMessage objQueueMessage = _objQueue.GetMessage(tsLease);
        T objItem = _objFactory.FromMessage(objQueueMessage);
        return objItem;
    }
}

现在我可以创建一个满足我标准的实例

 AzureQueue<Job> objJobQueue = new JobQueue(new JobItemFactory())

希望有一天这可以帮助其他人,显然很多内部代码被删除,试图显示问题和解决方案


#4楼

你可以用泛型技巧做到这一点,但它仍然容易受到Jon Skeet所写的影响:

public interface IHasDefaultConstructor<T> where T : IHasDefaultConstructor<T>, new()
{
}

实现此接口的类必须具有无参数构造函数:

public class A : IHasDefaultConstructor<A> //Notice A as generic parameter
{
    public A(int a) { } //compile time error
}

#5楼

强制某种构造函数的一种方法是在接口中声明只有Getters ,这可能意味着实现类必须有一个方法,理想情况下是一个构造函数,以便为它设置值( private )。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!