Шаг 201.
Язык программирования C#. Начала.
Перечисления и структуры. Структуры и интерфейсы

    На этом шаге мы рассмотрим использование интерфейсов в структурах.

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace pr201_1
{
    // Интерфейс:
    interface MyInterface {
        // Методы: 
        void set(int n); 
        void show();
    }

    // Структура наследует интерфейс: 
    struct MyStruct: MyInterface {
        // Закрытое целочисленное поле: 
        private int code;
        // Метод из интерфейса: 
        public void set(int n){ 
            code = n;
        }
        // Метод из интерфейса: 
        public void show() {
            Console.WriteLine("Числовое поле " + code);
        }
    }

    // Класс с главным методом:
    class Program
    {
        // Главный метод:
        static void Main()
        {
            // Создание экземпляра структуры:
            MyStruct A = new MyStruct();
            // Вызов метода для присваивания значения полю: 
            A.set(100);
            Console.WriteLine("Экземпляр A:");
            // Вызов метода для отображения значения поля: 
            A.show();
            // Интерфейсная переменная:
            MyInterface R;
            // Интерфейсной переменной значением присваивается
            // экземпляр структуры:
            R = A;
            Console.WriteLine("Переменная R:");
            // Вызов метода для отображения значения поля:
            R.show();
            // Вызов метода для присваивания значения полю:
            R.set(200);
            Console.WriteLine("Переменная R:");
            // Вызов метода для отображения значения поля:
            R.show();
            Console.WriteLine("Экземпляр A:");
            // Вызов метода для отображения значения поля:
            A.show();
            // Задержка:
            Console.ReadLine();
        }
    }
}
Архив проекта можно взять здесь.

    Результат выполнения программы следующий:


Рис.1. Результат выполнения программы

    Интерфейс называется MyInterface, и в нем объявлены два метода: метод set() с целочисленным аргументом и метод show() без аргументов (результат методы не возвращают). Структура MyStruct реализует интерфейс MyInterface. В структуре объявлено закрытое целочисленное поле code. Метод set() предназначен для присваивания значения полю code, а метод show() нужен для отображения значения поля.

    В методе Main() командой

  MyStruct A = new MyStruct();
создается экземпляр структуры. Создавать экземпляр нужно именно так (с использованием инструкции new), поскольку поле code закрытое, а перед вызовом любого метода поля должны быть инициализированы. Использованный нами способ создания экземпляра подразумевает вызов конструктора по умолчанию, вследствие чего поле code инициализируется с начальным нулевым значением.

    Значение 100 полю code экземпляра A присваиваем с помощью команды

  A.set(100);      . 
Для проверки значения поля экземпляра A используем команду
  A.show();     .

    Командой

  MyInterface R;
объявляется интерфейсная переменная. Поскольку структура MyStruct реализует интерфейс MyInterface, то интерфейсной переменной можно присвоить в качестве значения экземпляр структуры (команда
  R = A;
). Через интерфейсную переменную доступ будет только к тем методам, которые объявлены в интерфейсе. Но не это главное. Дело в том, что структура относится к типу данных с прямым доступом к значению. Поэтому при выполнении команды
  R = A; 
переменная R в качестве значения получает ссылку на копию экземпляра A.


При выполнении команды
  R = A; 
создается копия экземпляра A и ссылка на эту копию записывается в переменную R. Значением переменной R является ссылка, а не экземпляр. Интерфейсная переменная R ссылается на копию экземпляра A структуры MyStruct так же, как объектные переменные ссылаются на объекты классов. Если объявить еще одну интерфейсную переменную P интерфейса MyInterface, а затем выполнить команду
  P = R;     , 
то переменные P и R будут ссылаться на один и тот же экземпляр и этот экземпляр будет копией экземпляра A.

    Значение поля code экземпляра, на который ссылается интерфейсная переменная R, проверяем с помощью команды

  R.show();      . 
После выполнения команды
  R.set(200); 
меняется значение поля code экземпляра, на который ссылается интерфейсная переменная R. Значение поля code экземпляра A остается неизменным. Убеждаемся в этом с помощью команд
  R.show(); 
и
  A.show();      .

    На следующем шаге мы резюмируем все ранее сказанное по данной теме на предыдущих шагах.




Предыдущий шаг Содержание Следующий шаг