Использование интерфейса для прохождения метода - PullRequest
0 голосов
/ 17 октября 2019

У меня есть 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 голосов
/ 17 октября 2019

Вы путаете, что означает static. Когда метод влияет на конкретный экземпляр, как в этом случае, он должен быть нестатичным. Вот откуда взялась «странность».

Статические методы предназначены для общих операций или, хотя и с плюсами и минусами, как суррогат для синглетонов.

Вместо статического метода определите егокак член класса, который реализует IMoveable или как метод интерфейса по умолчанию. Без экземпляра в качестве параметра. Таким образом, экземпляр, this, будет двигаться. Вы сможете перемещаться, вызывая его из этого экземпляра, что семантически более логично:

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

Если каждый класс, реализующий интерфейс, перемещается одинаково, вы все равно можете избежать ссылки на экземплярв качестве параметра и используйте this. Возможно, параметры лучше всего использовать для информации о движении, если это необходимо.

...