Зачем создавать экземпляр интерфейса? [дубликат]

124
28 декабря 2019, 22:10
This question already has an answer here:
Интерфейс и его примеры (1 ответ)
Закрыт 9 месяцев назад.

Зачем создавать экземпляр интерфейса?

public interface IMyInterface { }
class Program
{
    private IMyInterface inter;
}
Answer 1

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

В Вашем коде показан не экземпляр интерфейса, а Интерфейсная ссылка. Интерфейсная ссылка - это переменная, ссылающаяся на метод, реализующий её интерфейс.

Пример использования интерфейсной ссылки:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace InterfaceExemplar
{
    public interface IMyInterface
    {
        void Function1();
        void Function2();
    }
    class Program
    {
        static void Main(string[] args)
        {
            Task task = new Task();
            IMyInterface inter;
            inter = task;
            inter.Function1();
            inter.Function2();
        }
    }
    class Task : IMyInterface
    {
        public void Function1()
        {
            Console.WriteLine("First Function");
        }
        public void Function2()
        {
            Console.WriteLine("Second Function");
        }
    }
}

Основные фрагменты кода:

1. Интерфейс IMyInterface, в котором находятся два метода: Function1 и Function2.

public interface IMyInterface
{
    void Function1();
    void Function2();
}

2. Класс Task, который наследует интерфейс IMyInterface и реализует все члены данного интерфейса.

class Task : IMyInterface
{
    public void Function1()
    {
        Console.WriteLine("First Function");
    }
    public void Function2()
    {
        Console.WriteLine("Second Function");
    }
}

3. В классе Programm реализуем экземпляр класса Task.Создаём интерфейсную ссылку и вызываем методы интерфейса IMyInterface.

class Program
{
    static void Main(string[] args)
    {
        Task task = new Task();
        IMyInterface inter;
        inter = task;
        inter.Function1();
        inter.Function2();
    }
}

Переменной inter доступны только те методы, которые объявлены в ее интерфейсе IMyInterface. Поэтому интерфейсную ссылку нельзя использовать для доступа к любым другим методам, которые не поддерживаются объектом класса, реализующего данный интерфейс.

Итог работы программы:

Надеюсь этот ответ был вам полезен.

Answer 2

Во-первых: Вы не можете создать экземпляр интерфейса, то есть использовать new:

// так работать не будет
IList list = new IList<object>();
// а так можно
IList list = new List<object>();

В приведённом Вами примере в классе Program просто объявляется поле с типом IMyInterface. Сохранить в него можно любой объект/экземпляр, который реализует этот интерфейс.

Теперь, на мой взгляд, самая важная часть вопроса: зачем...
Представьте, что у Вас имеется некий метод, который выводит в консоль текстовое представление каждого элемента List:

private WriteItemsToConsole(List<object> list) {
  foreach(var item in list) {
    Console.WriteLine(item.ToString());
  }
}

В приведённом выше примере используется просто итерация по листу и если в будущем Вам понадобится выводить в консоль не только содержимое List, но и к примеру содержимое массива, то при таком подходе придётся создавать перегруженный метод, который будет принимать параметром Array. Но нам в действительности не важно какой тип имеет передаваемый параметр, самое главное, чтоб он поддерживал нашу инструкцию foreach. Как раз это предоставляет интерфейс IEnumerable. Здесь и можно применить интерфейс, как тип параметра и тогда метод сможет печатать в консоль любые объекты/экземпляры, которые реализуют интерфейс IEnumerable:

private WriteItemsToConsole(IEnumerable<object> ienum) {
  foreach(var item in ienum) {
    Console.WriteLine(item.ToString());
  }
}

Ещё пример. Представьте, что Вы определяете следующие классы:

public class Person {
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public bool IsDeleted { get; set; }
}
public class Product {
  public string Name { get; set; }
  public bool IsDeleted { get; set; }
}
public class Contract {
  public Guid ContractId { get; set; }
  public bool IsDeleted { get; set; }
}

Не смотря на то, что они относятся к разным сущностям, все они имеют одно одинаковое свойство - IsDeleted, которое указывает на то, что сущность была логически удалена и не должна включаться в операции выборки из БД (по-моему такой подход называется "мягким удалением"). Если всё оставить так как есть, то Вы столкнётесь с проблемами при работе со свойством IsDeleted, так как нет никакого интерфейса (читай соглашения) об этом свойстве, оно не объявлено в каком-либо общем для них всех родительском классе и Вам придётся явно указывать тип (Person, Product, etc.). Здесь тоже можно (скорее всего нужно) использовать интерфейс:

public interface ISoftDelete {
  bool IsDeleted { get; set; }
}
public class Person : ISoftDelete {
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public bool IsDeleted { get; set; }
}
public class Product : ISoftDelete {
  public string Name { get; set; }
  public bool IsDeleted { get; set; }
}

Теперь при необходимости доступа к свойству IsDeleted Вам не нужно указывать все возможные варианты, а достаточно указать тип ISoftDelete и Вы получите доступ к свойству IsDeleted вне зависимости от того в каком типе оно определено.

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

READ ALSO
Как скачать файл на сервер средствами PHP?

Как скачать файл на сервер средствами PHP?

Вопрос такой, есть вот такой сайт, на котором есть кнопка "Выгрузить в календарь"По ее нажатию высвечивается модальное окно с кнопкой "Выгрузить"

159
Как возвращать ответ от Jq ajax на php

Как возвращать ответ от Jq ajax на php

Например, если ответ {"event":"success"}, то Вы можете обработать ответ так:

128
Отправка файлов из input type=&#39;file&#39;

Отправка файлов из input type='file'

Есть форма отправки на сайте

152
Вывод постов на страницу по условию

Вывод постов на страницу по условию

Имеем следующую форму с выбором даты:

157