Как я могу реализовать метод интерфейса, который принимает любые параметры? - PullRequest
1 голос
/ 25 марта 2020

У меня есть EnemyManager, который обрабатывает экземпляры классов, которые реализуют интерфейс: IEnemy.

public class EnemyManager
{
   public void AddEnemy(IEnemy enemy)
   {
      // Initialize enemy ...
   }
}

public interface IEnemy
{
   void Init<T>(T enemyData);
}

Я хочу, чтобы каждый экземпляр инициализировался с другим пользовательским типом: EvilSkeletonData, BossEnemyData ... et c , Но я не хочу создавать перегрузку для каждого из этих типов данных, чтобы поддерживать мой интерфейс как можно более чистым.

Я думал, что Generics мог бы работать, но, возможно, это противоречит цели, так как мне нужно было бы явно преобразовать данные в каждой реализации IEnemy:

public class EvilSkeleton : IEnemy
{
   public void Init<T>(T enemyData)
   {
      var enemyData = initParams as EvilSkeletonData;
      if(enemyData != null)
      {
          // Logic here
      } 
   }
}

Что будет чистым (и если возможно эффективный) способ решить эту проблему?

Ответы [ 2 ]

2 голосов
/ 26 марта 2020

Вы можете управлять универсальным c IEnemy интерфейсом, чтобы использовать его с некоторыми пользовательскими данными (такими как EvilSkeletonData, BossEnemyData и т. Д. 1014 *), вместо того, чтобы иметь просто c Init метод. И не универсальная c версия, чтобы иметь какие-либо общие данные для любого врага (например, здоровье)

public interface IEnemy
{
    int Health { get; set; }
}

public interface IEnemy<in T> : IEnemy
{
    void Init(T enemyData);
}

public class EvilSkeletonData
{
}

public class EvilSkeleton : IEnemy<EvilSkeletonData>
{
    public int Health { get; set; }

    public void Init(EvilSkeletonData enemyData)
    {
    }
}

Не универсальный c IEnemy интерфейс также позволяет вам правильно передать экземпляр AddEnemy метод в EnemyManager классе, в противном случае вы столкнетесь с некоторыми проблемами приведения и общих c дисперсий. Вы можете использовать его следующим образом

var manager = new EnemyManager();

var skeleton = new EvilSkeleton();
skeleton.Init(new EvilSkeletonData());

manager.AddEnemy(skeleton);
1 голос
/ 26 марта 2020

Чтобы уточнить, я говорил об этом в комментариях (если я вас правильно понимаю):

public interface IEnemy
{
    void Init(object enemyData);
}

public interface IEnemy<T> : IEnemy
{
    void Init(T enemyData);
}

public class EvilSkeleton : IEnemy<EvilSkeletonData>
{
    public void Init(EvilSkeletonData enemyData)
    {
        // Logic here
    }

    void IEnemy.Init(object enemyData) => Init((EvilSkeletonData)enemyData);
}

public class EnemyManager
{
    public void AddEnemy(IEnemy enemy)
    {
        // Initialize enemy ...
        enemy.Init(new EvilSkeletonData());
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...