很奇怪,这是我第一次遇到这个问题,但是:
如何在c#接口中定义构造函数?
编辑
有些人想要一个例子(这是一个自由时间项目,所以是的,这是一个游戏)
IDrawable
+更新
+画
为了能够更新(检查屏幕边缘等)和绘制本身,它总是需要一个GraphicsDeviceManager。我想确保对象有一个指向它的引用。这将属于构造函数。
现在我把这个写下来了,我想我在这里实现的是IObservable GraphicsDeviceManager应该采用IDrawable。
似乎不是我没有理解XNA框架,就是这个框架没有考虑得很好。
编辑
我在接口上下文中对构造函数的定义似乎有些混乱。接口确实不能被实例化,因此不需要构造函数。我想定义的是构造函数的签名。就像接口可以定义某个方法的签名一样,接口也可以定义构造函数的签名。
如前所述,在接口上不能有构造函数。但是,由于这是7年后谷歌中排名如此高的结果,我想我应该在这里补充一下——具体来说,是为了展示如何将抽象基类与现有的接口一起使用,并且可能会减少将来在类似情况下所需的重构量。在一些评论中已经暗示了这个概念,但我认为值得展示如何实际做到这一点。
到目前为止你的主界面是这样的:
public interface IDrawable
{
void Update();
void Draw();
}
现在用要强制的构造函数创建一个抽象类。实际上,自从你写你最初的问题以来,它就已经可用了,我们可以在这里稍微花点时间,在这种情况下使用泛型,这样我们就可以适应其他可能需要相同功能但有不同构造函数要求的接口:
public abstract class MustInitialize<T>
{
public MustInitialize(T parameters)
{
}
}
现在你需要创建一个继承IDrawable接口和MustInitialize抽象类的新类:
public class Drawable : MustInitialize<GraphicsDeviceManager>, IDrawable
{
GraphicsDeviceManager _graphicsDeviceManager;
public Drawable(GraphicsDeviceManager graphicsDeviceManager)
: base (graphicsDeviceManager)
{
_graphicsDeviceManager = graphicsDeviceManager;
}
public void Update()
{
//use _graphicsDeviceManager here to do whatever
}
public void Draw()
{
//use _graphicsDeviceManager here to do whatever
}
}
然后只需创建一个Drawable实例,就可以了:
IDrawable drawableService = new Drawable(myGraphicsDeviceManager);
这里很酷的是,我们创建的新Drawable类仍然像我们期望的IDrawable一样。
如果需要向MustInitialize构造函数传递多个参数,可以创建一个类,为需要传递的所有字段定义属性。
通用工厂方法似乎仍然是理想的。您将知道工厂需要一个形参,而这些形参恰好被传递给正在实例化的对象的构造函数。
注意,这只是经过语法验证的伪代码,这里可能忽略了一个运行时警告:
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对象。
我发现解决这个问题的一个方法是将施工分离到一个单独的工厂。例如,我有一个名为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()约束的情况下编写泛型队列类了,在我的例子中,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())
希望有一天这能帮助其他人解决问题,显然,为了显示问题和解决方案,删除了大量内部代码