我有一个界面static float speed = 30; // move speed outside method to not create it each frame.
private void playerMovement() {
if(Gdx.input.isKeyPressed(Input.Keys.W)){
body.setLinearVelocity(0f, speed); // removed Vector2(), it's not a good idea to cteate it each frame.
}if(Gdx.input.isKeyPressed(Input.Keys.S)){
body.setLinearVelocity(0f, -speed);
}if(Gdx.input.isKeyPressed(Input.Keys.A)){
body.setLinearVelocity(-speed, 0f);
}if(Gdx.input.isKeyPressed(Input.Keys.D)){
body.setLinearVelocity(speed,0f);
}if(Gdx.input.isKeyPressed(Input.Keys.W) && Gdx.input.isKeyPressed(Input.Keys.A)){
body.setLinearVelocity(-speed, speed);
}if(Gdx.input.isKeyPressed(Input.Keys.W) && Gdx.input.isKeyPressed(Input.Keys.D)){
body.setLinearVelocity(speed, speed);
}if(Gdx.input.isKeyPressed(Input.Keys.S) && Gdx.input.isKeyPressed(Input.Keys.A)){
body.setLinearVelocity(-speed, -speed);
}if(Gdx.input.isKeyPressed(Input.Keys.S) && Gdx.input.isKeyPressed(Input.Keys.D)){
body.setLinearVelocity(speed, -speed);
}else {
body.setLinearVelocity(0f,0f);
}
}
:
IPopUp
我有几个实现:public interface IPopUp
{
bool IsCancelable {get;}
void Show();
void Close();
Action MainAction{ get; }
Action CancelAction{ get; }
}
,IfoPopUp
和ErrorPopUp
我正在使用LoadingPopUp
实例
PopUps
的实例
PopUpManager
我不知道如何强制 public class PopUpManager
{
public void ShowPopUp<T>(string texto) where T:IPopUp
{
ShowPopup (()=>(IPopUp)Activator.CreateInstance (typeof(T)));
}
public void ShowPopUp<T>(string texto,Action mainAction)where T:IPopUp
{
ShowPopup (()=>(IPopUp)Activator.CreateInstance (typeof(T), mainAction));
}
public void ShowPopUp<T>(string texto,Action mainAction,Action cancelAction)where T:IPopUp
{
ShowPopup (()=>(IPopUp)Activator.CreateInstance (typeof(T), mainAction, cancelAction));
}
private void ShowPopup(Func<IPopUp> factoryFunc)
{
if (PopUpShowed != null) {
PopUpShowed.Close ();
}
IPopUp popUp = factoryFunc ();
popUp.Show ();
}
}
实现来实现我在IPopUp
中使用的3种构造函数。
抽象类不会起作用,因为它可以强制构造函数......
有什么想法吗?
答案 0 :(得分:1)
我最终通过重构类PopUpManager
,因此需要工厂委托才能生成PopUpManager
。
很清楚,实例化PopUps的责任来自于有很大意义的调用者。
PopUp
无论如何,我有兴趣知道哪种方法最好强制类实现一些构造函数。
答案 1 :(得分:1)
您已经找到了一个很好的解决方案。这里有一些关于强制类实现某些构造函数的其他见解。
C# language specification 5.0在第13章中定义了什么是接口:
接口定义合同。实现一个的类或结构 接口必须遵守其合同。接口可以继承 多个基接口,类或结构可以实现多个 接口。
接口可以包含方法,属性,事件和 索引。接口本身不提供实现 它定义的成员。界面只是指定了 必须由实现该类的类或结构提供的成员 接口
实例构造函数不是方法,不能是接口的一部分。这在13.2中明确提醒:
接口不能包含常量,字段,运算符,实例 构造函数,析构函数或类型,接口也不能包含 任何形式的静态成员。
有很多理由可以证明这种语言设计的选择,你可以在SO上找到一些额外的解释。另请注意,其他语言具有类似的约束。例如,Java声明“接口可能无法直接实例化。”
C#语言规范在10.1.1.1节中说明。那个:
abstract修饰符用于指示类是不完整的 并且它仅用作基类。 (...)抽象类不能直接实例化,在抽象类上使用new运算符是编译时错误。
简而言之,如果要在抽象类中定义三个不同的构造函数,派生类必须调用其中一个构造函数,但不对它们自己的构造函数赋予任何约束。请注意,此逻辑也适用于C ++或Java。
抽象类与其派生类的链接类似于实现{{1}的Shape
与Square
,Rectangle
和Circle
之间的链接}:Rectangle的构造参数可能与Circle的构造参数非常不同,因此Shape
不能将约束放在其子元素的构造函数上。
您希望Shape
实例化具有某些属性的PopupManager
。不幸的是,您无法以安全的方式直接实例化IPopUp
(Activator.CreateInstance()可能会触发异常)。
为了确保安全,您可以强制IPopUp
要求IPopUp
和MainAction
的设置器,并添加构造函数约束(例如CancelAction
)来制作确保可以毫无意外地创建实例,并更改对象以满足需要。
但在某些情况下,需要在施工时提供参数。在这种情况下,您可以考虑使用您选择的builder pattern或工厂方法。请注意,在允许具有静态成员的接口的语言中,您甚至可以在where T:IPopUp, new()
接口中强制使用三个静态工厂方法。
答案 2 :(得分:0)
我有类似的问题。在我的例子中,具有特定属性[SpecialAttribute]
的类需要具有无参数构造函数。
我在每次构建后添加了一个在CI服务器上运行的测试,其中搜索具有该属性的类,然后调用Activator.CreateInstance
。如果由MissingMethodException
s导致失败,则该测试“失败”并显示缺少无参数构造函数的类。
这并不完美,因为代码仍然可以编译。但是一个失败的自动化测试和明确的信息是向前迈出的重要一步。