使用接口传递方法

时间:2019-10-17 11:31:50

标签: c# interface xna monogame

我有2个以上的对象来自不同的继承树,但我希望它们共享一组公共代码IMoveable

IMoveable界面看起来不错,我对它的使用感到满意:

public interface IMoveable
{
  /// <summary>
  /// The speed the object travells between start and end
  /// </summary>
  int Speed { get; set; }

  /// <summary>
  /// The current velocity of the object
  /// </summary>
  Vector2 Velocity { get; set; }

  /// <summary>
  /// How far the object has travelled
  /// </summary>
  int DistanceTravelled { get; set; }

  /// <summary>
  /// The map the object is traversing
  /// </summary>
  Map Map { get; set; }

  /// <summary>
  /// Where the object was when they started moving
  /// </summary>
  Rectangle StartRectangle { get; set; }

  /// <summary>
  /// Where the object is right now
  /// </summary>
  Rectangle CurrentRectangle { get; }

  /// <summary>
  /// Where the object will be after moving
  /// </summary>
  Rectangle EndRectangle { get; set; }

  /// <summary>
  /// What will happen if the object walks to the "EndRectangle"
  /// </summary>
  Map.CollisionResults CollisionResult { get; set; }

  /// <summary>
  /// What happens if the object triggers a battle
  /// </summary>
  Action OnBattle { get; set; }

  /// <summary>
  /// How the object determines their movement
  /// </summary>
  Action SetMovement { get; set; }
}

使用该接口,我有一个方法:

 private static void Move(IMoveable moveableOjb)
  {
    moveableOjb.Speed = 4;

    if (moveableOjb.DistanceTravelled > 0)
    {
      moveableOjb.DistanceTravelled += moveableOjb.Speed;

      if (moveableOjb.DistanceTravelled > Map.TileWidth)
      {
        moveableOjb.DistanceTravelled = 0;
        moveableOjb.Velocity = new Vector2();
      }
      else
      {
        return;
      }
    }

    moveableOjb.SetMovement();

    if (moveableOjb.Velocity != Vector2.Zero)
    {
      moveableOjb.StartRectangle = moveableOjb.CurrentRectangle;
      moveableOjb.EndRectangle = new Rectangle(
        moveableOjb.CurrentRectangle.X + ((int)moveableOjb.Velocity.X * 10),
        moveableOjb.CurrentRectangle.Y + ((int)moveableOjb.Velocity.Y * 10),
        moveableOjb.CurrentRectangle.Width,
        moveableOjb.CurrentRectangle.Height);

      moveableOjb.CollisionResult = moveableOjb.Map.GetValue(moveableOjb.EndRectangle);

      switch (moveableOjb.CollisionResult)
      {
        case Map.CollisionResults.None:
          break;
        case Map.CollisionResults.Colliding:
          moveableOjb.Velocity = new Vector2();
          break;
        case Map.CollisionResults.Battle:
          moveableOjb.OnBattle();
          moveableOjb.Velocity = new Vector2();
          break;
        case Map.CollisionResults.OffRight:
        case Map.CollisionResults.OffLeft:
        case Map.CollisionResults.OffTop:
        case Map.CollisionResults.OffBottom:
          moveableOjb.Speed = 0;
          break;
        default:
          break;
      }
    }

    if (moveableOjb.Velocity != Vector2.Zero)
      moveableOjb.DistanceTravelled += moveableOjb.Speed;
  }

我面临的问题是这段代码很奇怪。我有一个静态的Move方法,但我不知道将其放在哪里,而且我觉得我已经完全以错误的方式解决了这个问题。

对此,我必须采取的另一种方法是重写我的类,因此它们位于同一棵树中,而不是来自不同的继承。我可以这样做,但是要花一些时间进行重组。

我想我的主要问题是-我会以错误的方式进行操作,还是接近无法完全弄清的编码实践?

实施示例:

public class ClassA : Sprite, IMoveable
{
  // interface implementation

  public override Update(GameTime gameTime)
  {
    // Stuff

    Move(this);        

    // More stuff
  }
}

编辑:

我们已经得知,使用C#8可以使用默认的接口方法。我认为这可能正是我所需要的!

1 个答案:

答案 0 :(得分:0)

您对static的含义感到困惑。当方法影响特定实例时(如本例所示),它应该是非静态的。这就是“怪异”的来源。

静态方法适用于一般操作,或者虽然有利有弊,但也可以作为单例的替代方法。

将其定义为实现IMoveable的类的成员或默认接口方法,而不是静态方法。没有实例作为参数。这样,实例this将移动。您可以通过从该实例调用它来进行移动,这在语义上更有意义:

IMoveable moveableObj = //constructor here...
moveableObj.Move();

如果每个实现该接口的类都以相同的方式移动,您仍然可以避免将对实例的引用作为参数,而使用this。必要时,也许这些参数最适合用于有关运动的信息。