这是我第一次碰到这个问题,这很奇怪,但是:
如何在C#接口中定义构造函数?
编辑
有些人想要一个例子(这是一个空闲时间项目,所以是的,这是一个游戏)
IDrawable
+更新
+绘制
为了能够更新(检查屏幕边缘等)并绘制自身,它将始终需要GraphicsDeviceManager
。 所以我想确保对象有引用它。 这将属于构造函数。
现在我写下来了,我认为我在这里实现的是IObservable
, GraphicsDeviceManager
应该使用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
)。
来源:oschina
链接:https://my.oschina.net/u/3797416/blog/3158268