Опубликован: 25.03.2010 | Доступ: свободный | Студентов: 1447 / 158 | Оценка: 4.31 / 4.00 | Длительность: 25:42:00
Лекция 9:

Наследование в C#

Сокрытие имен при наследовании

Находясь внутри производного класса мы можем видеть как-бы два слоя членов: члены производного класса на переднем плане и члены базового класса на заднем плане. Производный и базовый классы могут иметь члены с одинаковыми именам и. Это не является ошибкой, и даже компилятор не выдаст предупреждение, что будет использован член производного класса. Лишь текстовый редактор оболочки напомнит подчеркиванием, что имя члена в производном классе, находящееся в переднем слое, скрывает имя члена базового класса и желательно использовать ключевое слово new, но можно обойтись и без него. Употребление ключевого слова new в данном контексте свидетельствует лишь о том, что программист извещен и знает, что делает. Вот пример

using System;
    
namespace Test
{
    class A
    {
        protected int x; // Член класса A будет виден в наследниках
    
        public A(int a)
        {
            x = a;
        }
    
        public A()// Обязаны определить
        { }
    
        protected int Get() // Член класса A будет виден в наследниках
        {
            return x;
        }
    }
    
    class Empty : A
    {
        public Empty(int a)
            : base(a)
        { }
    
        public Empty() { }  // Обязаны определить, 
                            // если определен в базовом классе
    }
    
    class B : Empty
    {
        new int x; // Член класса B, одноименный с унаследованным
    
        public B(int a, int b)
            : base(a)
        {
            x = b;  // Значение присваивается члену текущего класса
        }
    
        public B(int x)
        {
            base.x = 10;// Значение присваивается члену базового класса
            this.x = x; // Значение присваивается члену текущего класса
        }
    
        new int Get() // Член класса B, одноименный с унаследованным
        {
            return x;
        }
    
        public void Show()
        {
            int sumOfSquares =
                base.Get() * base.Get() // Используется унаследованный член 
                + Get() * Get();    // Используется член текущего класса
            Console.WriteLine("Сумма квадратов: 
    {0}", sumOfSquares);
        }
    }
    
    // Вызывающий код
    class Program
    {
        static void Main()
        {
            // Настройка консоли
            Console.Title = "Сокрытие унаследованных имен";
            Console.ForegroundColor = ConsoleColor.White;
            Console.CursorVisible = false;
            Console.WindowWidth = 60;
            Console.WindowHeight = 10;
    
            B ob = new B(1, 2);
            ob.Show();
            Console.WriteLine("Контрольная сумма 
    квадратов: {0}", 1 + 4);
            Console.WriteLine();
    
            ob = new B(5);// Использование ссылки для другого объекта
            ob.Show();
            Console.WriteLine("Контрольная сумма квадратов: 
    {0}", 125);
    
            Console.ReadLine();
        }
    }
}
Листинг 9.7 . Доступ к одноименным членам в цепочке наследования

Ключевое слово base в данном контексте используется для доступа к члену базового класса, ближайшему в многоуровневой цепочке наследования, содержащему одноименный член. Промежуточный класс Empty здесь как раз и приведен для иллюстрации того, что одноименный член не обязательно может находиться в соседнем базовом классе.

Последовательность срабатывания конструкторов

В многоуровневой цепочке наследования производный класс стоит в самом низу иерархической лестницы. Если создается объект этого составного класса, то срабатывание конструкторов выполняется в сторону производного класса, начиная с конструктора базового класса, в порядке их выведения. Деструкторы срабатывают в обратном порядке и только при активизации сборщика мусора ( GC - Garbare Collector ). Вот пример

using System;
    
namespace Test
{
    class A
    {
        public A()
        {
            Console.WriteLine("Сработал конструктор A");
        }
    
        ~A()
        {
            Console.WriteLine("Сработал деструктор A");
        }
    }
    
    class B : A
    {
        public B()
        {
            Console.WriteLine("Сработал конструктор B");
        }
    
        ~B()
        {
            Console.WriteLine("Сработал деструктор B");
        }
    }
    
    class C : B
    {
        public C()
        {
            Console.WriteLine("Сработал конструктор C");
        }
    
        ~C()
        {
            Console.WriteLine("Сработал деструктор C");
        }
    }
    
    class D : C
    {
        public D()
        {
            Console.WriteLine("Сработал конструктор D");
        }
    
        ~D()
        {
            Console.WriteLine("Сработал деструктор D");
        }
    }
    
    // Вызывающий код
    class Program
    {
        static void Main()
        {
            // Настройка консоли
            Console.Title = "Вызовы конструкторов и деструкторов";
            Console.ForegroundColor = ConsoleColor.White;
            Console.CursorVisible = false;
            Console.WindowWidth = 60;
            Console.WindowHeight = 10;
    
            D ob = new D(); // Создаем объект
            ob = null;  // Теряем объект, чтобы сработали деструкторы
            Console.WriteLine();// Новая строка в выводе
    
            GC.Collect();// Принудительно вызываем сборщик мусора
            GC.WaitForPendingFinalizers();  // Приостанавливаем текущий поток
                                            // до завершения уборки
    
            Console.ReadLine();
        }
    }
}
Листинг 9.8 . Порядок срабатывания конструкторов и деструкторов в иерархической лестнице

Результат вывода будет таким


Порядок корректного срабатывания конструкторов и деструкторов удобно представить как модель строительства и разрушения многоэтажного дома


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

Максим Филатов
Максим Филатов

Прошел курс. Получил код Dreamspark. Ввожу код на сайте, пишет:

Срок действия этого кода проверки уже истек. Проверьте, правильно ли введен код. У вас осталось две попытки. Вы также можете выбрать другой способ проверки или предоставить соответствующие документы, подтверждающие ваш академический статус.

 

Как активировать код?