Шаг 158.
Язык программирования C#. Начала.
Абстрактные классы и интерфейсы. Знакомство с интерфейсами (окончание)

    На этом шаге мы рассмотрим еще один пример использования интерфейсов.

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

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

namespace pr158_1
{
    // Базовый абстрактный класс: 
    abstract class Base {
        // Объявление абстрактного свойства: 
        public abstract int number { 
            get; 
            set;
        }
        // Конструктор с одним аргументом: 
        public Base(int n) {
            // Присваивание значения свойству: 
            number = n;
            // Вызывается обычный (не абстрактный) метод: 
            show();
        }
        // Описание обычного (не абстрактного) метода: 
        public void show() {
            // Отображение значения свойства: 
            Console.WriteLine("Свойство number = " + number);
        }
    }

    // Первый интерфейс:
    interface First {
        // Объявление методов: 
        void setNum(int n); 
        int getNum();
    }

    // Второй интерфейс:
    interface Second {
        // Объявление индексатора: 
        int this[int k]{ 
            get;
        }
    }

    // Класс реализует интерфейс:
    class MyClass: Base, First, Second {
        // Закрытое целочисленное поле: 
        private int num;
        // Конструктор с одним аргументом: 
        public MyClass(int n): base(n) {}
        // Описание метода из интерфейса First: 
        public void setNum(int n) {
            // Присваивание значения полю: 
            num = n;
        }
        // Описание метода из интерфейса First: 
        public int getNum() {
            // Значение поля: 
            return num;
        }
        // Описание свойства из класса Base: 
        public override int number {
            // Аксессор для считывания значения: 
            get {
                // Вызывается метод из интерфейса First: 
                return getNum();
            }
            // Аксессор для присваивания значения: 
            set {
                // Вызывается метод из интерфейса First: 
                setNum(value);
            }
        }
        // Описание индексатора из интерфейса Second: 
        public int this[int k] {
            // Аксессор для считывания значения: 
            get {
                // Локальная переменная: 
                int r = number;
                // "Отбрасывание" цифр в десятичном 
                // представлении числа: 
                for(int i = 0; i < k; i++) { 
                    r /= 10;
                }
                // Результат: 
                return r % 10;
            }
        }
    }

    // Класс с главным методом:
    class Program
    {
        static void Main()
        {
            int m = 9;
            MyClass obj = new MyClass(12345); 
            for (int i = 0; i <= m; i++)
            {
                Console.Write("|" + obj[m - i]);
            }
            Console.WriteLine("|");
            // Задержка:
            Console.ReadLine();
        }
    }
}
Архив проекта можно взять здесь.

    Ниже показано, как выглядит результат выполнения программы:


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

    Результат выполнения программы такой же, как и в предыдущем случае. Это неудивительно, поскольку представленный выше пример является вариацией предыдущего. Мы просто немного иначе организовали программный код. Если раньше у нас был один интерфейс MyInterface, на основе которого создавался класс MyClass, то теперь имеется абстрактный класс Base, на основе которого путем наследования создается класс MyClass. При этом класс MyClass реализует интерфейсы First и Second.

    В классе Base объявляется абстрактное свойство number, причем поскольку теперь свойство объявляется не в интерфейсе, а в абстрактном классе, то мы используем в объявлении ключевое слово abstract. Также мы явно указали спецификатор уровня доступа public для свойства. При описании свойства в классе MyClass использовано ключевое слово override.

    В классе Base описан конструктор с целочисленным аргументом. Этот аргумент присваивается значением свойству number. После присваивания вызывается метод show(). Последний также описан в классе Base, причем хотя метод обычный (не абстрактный), но в теле метода (как и в теле конструктора) выполняется обращение к абстрактному свойству number.

    В интерфейсе First объявлены методы setNum() и getNum(). В интерфейсе Second объявлен индексатор с целочисленным индексом. Индексатор должен возвращать целое число, и у него должен быть get-аксессор.

    Как отмечалось выше, класс MyClass наследует абстрактный класс Base и реализует интерфейсы First и Second. Поэтому в классе MyClass описываются свойство number из класса Base, методы getNum() и setNum() из интерфейса First, а также индексатор из интерфейса Second. Соответствующий код должен быть понятен.


Как и в примере из предыдущего шага, класс MyClass содержит закрытое целочисленное поле num. Конструктор класса MyClass описан таким образом, что переданный конструктору целочисленный аргумент далее передается конструктору базового класса. Никаких дополнительных действий не выполняется, поэтому тело конструктора представляет собой пустой блок.

    В главном методе содержатся те же команды, что и в примере из предыдущего шага.

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




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