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

    На этом шаге мы рассмотрим отличие переопределения от перегрузки методов.

    Мы познакомились с переопределением метода, когда в производном классе описывается новая версия унаследованного метода. В данном случае речь идет о полном совпадении типа, названия и списка аргументов метода в базовом и производном классах. Но еще есть такой механизм, как перегрузка методов. При перегрузке метода описывается несколько версий этого метода. Для каждой версии название одно и то же, но вот списки аргументов должны отличаться. Эти два механизма (перегрузка и переопределение) могут использоваться одновременно. В примере ниже представлена программа, в которой на фоне наследования используется перегрузка и переопределение методов.

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

namespace pr147_1
{
    // Базовый класс: 
    class Alpha {
        // Целочисленное поле: 
        public int alpha; 
        // Метод без аргументов: 
        public void set() { 
            // Значение поля: 
            alpha = 10;
            // Отображение значения поля:
            Console.WriteLine("Alpha (без аргументов): {0}", alpha);
        }
        // Метод (виртуальный) с одним аргументом: 
        public virtual void set(int n) {
            // Значение поля: 
            alpha = n;
            // Отображение значения поля:
            Console.WriteLine ("Alpha (один: аргумент): {0}", alpha);
        }
    }

    // Производный класс: 
    class Bravo: Alpha {
        // Целочисленное поле: 
        public int bravo;
        // Переопределение виртуального метода: 
        public override void set(int n) {
            // Присваивание значений полям:
            alpha = n;
            bravo = alpha;
            // Отображение значений полей:
            Console.WriteLine("Bravo (один аргумент): {0} и {1}", alpha, bravo);
        }
        // Метод с двумя аргументами: 
        public void set(int m, int n) {
            // Присваивание значений полям:
            alpha = m;
            bravo = n;
            // Отображение значений полей:
            Console.WriteLine("Bravo (два аргумента): {0} и {1}", alpha, bravo);
        }
    }

    // Класс с главным методом:
    class Program
    {
        // Главный метод:
        static void Main()
        {
            // Создание объекта базового класса:
            Alpha A = new Alpha();
            // Вызов методов:
            A.set();
            A.set(20);
            Console.WriteLine();
            // Создание объекта производного класса:
            Bravo B = new Bravo();
            // Вызов методов:
            B.set();
            B.set(30);
            B.set(40, 50);
            // Задержка:
            Console.ReadLine();
        }
    }
}
Архив проекта можно взять здесь.

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


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

    У нас есть два класса: Alpha и Bravo, причем класс Bravo является производным от класса Alpha. В классе Alpha имеется открытое целочисленное поле alpha, которое наследуется в классе Bravo. Еще в классе Bravo появляется целочисленное поле bravo. В классе Alpha описаны две версии метода set(): без аргументов и с одним аргументом. Версия метода set() с одним аргументом описана как виртуальная (использовано ключевое слово virtual). В классе Bravo появляется еще одна версия метода set() с двумя аргументами, а версия метода с одним аргументом переопределяется (она описана с ключевым словом override). Каждая версия метода описана так, что полю или полям присваиваются значения, после чего в консольное окно выводится сообщение с указанием названия класса, количества аргументов у метода и фактического значения поля или полей объекта. Таким образом, по сообщению, отображаемому в консольном окне при вызове метода, можно однозначно определить, какая версия метода была вызвана.

    В главном методе программы мы создаем объект А класса Alpha и объект B класса Bravo. Из каждого объекта вызываются разные версии метода set(). Для объекта А это две версии (обе описаны в классе Alpha): без аргументов и с одним аргументом. Для объекта В таких версий три. Это, во-первых, версия метода без аргументов, унаследованная из класса Alpha. Во-вторых, переопределенная в классе Bravo версия метода с одним аргументом. И в-третьих, версия с двумя аргументами, описанная в классе Bravo.

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




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