Для чего используется кастинг интерфейса в C #?

#c# #interface #casting

#c# #интерфейс #Кастинг

Вопрос:

Я понимаю, как работает написание интерфейса на C #, как, например, описано здесь: объяснение codeguru

 interface IIntelligence
   {
      bool intelligent_behavior();
   }

   class Human: IIntelligence
   {
      public Human()
      {
          //.............
      }

/// Interface method definition in the class that implements it
      public bool intelligent_behavior()
      {
         Console.WriteLine("........");
         return true
      }
   }
  

Однако меня смущает следующий процесс кастинга интерфейса:

 Human human = new Human();
// The human object is casted to the interface type
IIntelligence humanIQ = (IIntelligence)human;
humanIQ.intelligent_behavior();
  

Какой смысл в том, чтобы класс (в данном случае Human) реализовал интерфейс, а затем вернул свой экземпляр human обратно в интерфейс? Вопрос не в том, как это работает, а в том, почему это делается.

Ответ №1:

.net предлагает два типа реализаций интерфейса — неявную реализацию и явную реализацию.

Когда вы используете неявную реализацию, она станет частью самого интерфейса типа, например, если у вас есть интерфейс IPerson, подобный этому :

 public interface IPerson
{
string Name{get;}
}
  

и вы реализуете это следующим образом :

 public class Person:IPerson
{
public string Name{get; ....}
}
  

вы можете получить к нему доступ следующим образом (неявно):

 aPerson.Name;
  

но если вы реализуете это вот так (явно) :

 public class Person:IPerson
{
string IPerson.Name{get; ....} // notice that there's no need to include access modifier.
}
  

Тогда к нему можно получить доступ только с помощью интерфейса IPerson:

 ((IPerson)aPerson).Name;
  

Обновить:

На самом деле, явная реализация интерфейса позволяет нам реализовывать разные интерфейсы с элементами, имеющими одинаковое имя.(как показано в этом руководстве)

Ответ №2:

Иногда вы можете не знать, что такое объект, но вы знаете, что он реализует определенный интерфейс.

Комментарии:

1. Может случиться, я думаю, вы бы сделали baseObject is IInterface для проверки. Любопытно, что параметр метода IInterface еще не введен.

Ответ №3:

Краткий и популярный пример. Мы можем реализовать такой код: interface IIntelligence { string Talk(); }

    class Cat: ICreature
   {
      public string Talk()
      {
         Console.WriteLine("Meow!");
         return true
      }
   }

   class Dog: ICreature
   {
      public string Talk()
      {
         Console.WriteLine("Arf!");
         return true
      }
   }

   class Human: ICreature
   {
      public string Talk()
      {
         Console.WriteLine("Hello!");
         return true
      }
   }
  

И тогда мы можем использовать следующий код:

 ICreature() creatures = new ICreature(){new Human(), new Dog(), new Cat()};
foreach(IIntelligence creature in creatures){
  Console.WriteLine(creature.Talk());
}
  

Более подробную информацию смотрите в разделе «Полиморфизм в объектно-ориентированном программировании» в Google.

Ответ №4:

Это для получения доступа к явной реализации интерфейса.

Иногда вы хотите скрыть тот факт, что класс реализует интерфейс. Это делается путем явной реализации интерфейса.

 public class MyClass : IInterface
{
     string IInterface.TheMethod(){}
}
  

Ответ №5:

По той же причине, по которой вы приводите производный класс обратно к его базовому классу.

Ответ №6:

Рассмотрим эту ситуацию. Я добавил метод к вашему примеру.

 interface IIntelligence
{
    bool intelligent_behavior();
}

class Human: IIntelligence
{
    public Human() { }  

    /// Interface method definition in the class that implements it
    public bool IIntelligence.intelligent_behavior()
    {
        Console.WriteLine("........");
        return true;
    }    

    //Some other method definition
    public bool intelligent_behaviour()
    {
        return false;
    }
}
  

Вы бы выполнили приведение в IIntelligence , чтобы получить желаемую реализацию метода.

Ответ №7:

Я обнаружил, что приведение к интерфейсу полезно при разработке плагинов для основного приложения. Я создал три проекта. Первый проект ‘connectorInterface’ содержит только одно определение класса, которое является inteface. Код интерфейса:

 public interface IConnectorDataReader
{
  int ColumnCount
  {
    get;
  }

  bool readNextRecord();

  string this[int i]
  {
    get;
  }

  void reset();
}
  

Второй проект ‘DataSource1’ (плагин для основного приложения) реализует интерфейс IConnectorDataReader, а также класс, который реализует интерфейс, имеет некоторые дополнительные частные методы. Третий проект ‘main application’ при использовании плагина ‘DataSource1’ использует этот код для чтения данных из плагина ‘DataSource1’:

   Assembly assembly = Assembly.LoadFile(path); // path to dll
  Type type = assembly.GetType("dataSource1.DataReader");
  object myInstance = Activator.CreateInstance(type);

  MethodInfo method = type.GetMethod("getConnectorDataReader");
  object data = method.Invoke(myInstance, null);

  IConnectorDataReader reader =(IConnectorDataReader)data;

  // method usage
  while (reader.readNextRecord() == true) ....
  

В моем случае кастинг полезен для чтения данных плагинов. Мне все равно, как реализован плагин, главное, чтобы он реализовывал common interface. Все, что меня волнует и что я использую, — это обычные методы для чтения данных. Я полагаю, что интерфейсы полезны, а также возвращают к интерфейсам.