Интерфейсные ссылки

57

Как это ни покажется странным, но в C# допускается объявлять переменные ссылочного интерфейсного типа, т.е. переменные ссылки на интерфейс. Такая переменная может ссылаться на любой объект, реализующий ее интерфейс. При вызове метода для объекта посредством интерфейсной ссылки выполняется его вариант, реализованный в классе данного объекта. Этот процесс аналогичен применению ссылки на базовый класс для доступа к объекту производного класса.

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

using System;

namespace ConsoleApplication1
{
    public interface IInfo
    {
        void uiName();
        void uiFamily();
        void uiAge();
    }

    class UI : IInfo
    {
        string Name, Family;
        int Age;

        public UI(string Name, string Family, int Age)
        {
            this.Name = Name;
            this.Family = Family;
            this.Age = Age;
        }

        // Реализуем интерфейс
        public void uiName()
        {
            Console.WriteLine("Имя пользователя: " + Name);
        }

        public void uiFamily()
        {
            Console.WriteLine("Фамилия: " + Family);
        }

        public void uiAge()
        {
            Console.WriteLine("Возраст: " + Age);
        }

        // Собственный метод класса UI
        public void allInfo()
        {
            Console.WriteLine(Name + " " + Family + " " + Age);
        }
    }

    class Program
    {
        static void Main()
        {
            UI ui1 = new UI(Name: "Alexandr", Family: "Erohin", Age: 26);

            // Создадим ссылку на интерфейс
            IInfo obj;
            //Используем ссылку на объект ui1
            obj = ui1;
            obj.uiName();
            obj.uiFamily();
            obj.uiAge();
            // Вызов собственного метода не разрешается:
            // obj.allInfo();
            Console.ReadLine();
        }
    }
}
Ссылка на интерфейс

Ключевое слово as

Определить, поддерживает ли данный тип тот или иной интерфейс, можно с использованием ключевого слова as. Если объект удается интерпретировать как указанный интерфейс, то возвращается ссылка на интересующий интерфейс, а если нет, то ссылка null. Следовательно, перед продолжением в коде необходимо предусмотреть проверку на null.

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

IInfo obj = ui1 as IInfo;
if (obj != null)
   Console.WriteLine("Тип UI поддерживает интерфейс IInfo");
else
   Console.WriteLine(":(");

Обратите внимание, что в случае применения ключевого слова as использовать логику try/catch нет никакой необходимости, поскольку возврат ссылки, отличной от null, означает, что вызов осуществляется с использованием действительной ссылки на интерфейс.

Ключевое слово is

Проверить, был ли реализован нужный интерфейс, можно также с помощью ключевого слова is. Если запрашиваемый объект не совместим с указанным интерфейсом, возвращается значение false, а если совместим, то можно спокойно вызывать члены этого интерфейса без применения логики try/catch.

if (ui1 is IInfo)
  Console.WriteLine("Тип UI поддерживает интерфейс IInfo");
else
  Console.WriteLine(":(");
Пройди тесты
Лучший чат для C# программистов