Наследование
Мощь ООП основана на наследовании. Когда построен полезный класс, то он может многократно использоваться. Повторное использование - это одна из главных целей ООП. Но и для хороших классов неизбежно наступает момент, когда необходимо расширить возможности класса, придать ему новую функциональность, изменить интерфейс. Всякая попытка изменять сам работающий класс чревата большими неприятностями - могут перестать работать прекрасно работавшие программы, многим клиентам класса вовсе не нужен новый интерфейс и новые возможности. Здесь-то и приходит на выручку наследование. Существующий класс не меняется, но создается его потомок, продолжающий дело отца, только уже на новом уровне.
Класс-потомок наследует все возможности родительского класса - все поля и все методы, открытую и закрытую часть класса. Правда, не ко всем полям и методам класса возможен прямой доступ потомка. Поля и методы родительского класса, снабженные атрибутом private, хотя и наследуются, но по-прежнему остаются закрытыми, и методы, создаваемые потомком, не могут к ним обращаться напрямую, а только через методы, наследованные от родителя. Единственное, что не наследует потомок - это конструкторы родительского класса. Конструкторы потомок должен создавать сам. В этом есть некоторая разумная идея, и я позже поясню ее суть.
Рассмотрим класс, названный Found, играющий роль родительского класса. У него есть обычные поля, конструкторы и методы, один из которых снабжен новым модификатором virtual, ранее не появлявшимся в классах, другой - модификатором override:
public class Found
{
//поля
protected string name;
protected int credit;
public Found()
{
}
public Found(string name, int sum)
{
this.name = name; credit = sum;
}
public virtual void VirtMethod()
{
Console.WriteLine ("Отец: " + this.ToString() );
}
public override string ToString()
{
return(String.Format("поля: name = {0}, credit = {1}",
name, credit));
}
public void NonVirtMethod()
{
Console.WriteLine ("Мать: " + this.ToString() );
}
public void Analysis()
{
Console.WriteLine ("Простой анализ");
}
public void Work()
{
VirtMethod();
NonVirtMethod();
Analysis();
}
}
Заметьте, класс Found, как и все классы, по умолчанию является наследником класса Object, его потомки наследуют методы этого класса уже не напрямую, а через методы родителя, который мог переопределить методы класса Object. В частности, класс Found переопределил метод ToString, задав собственную реализацию возвращаемой методом строки, которая связывается с объектами класса. Как часто делается, в этой строке отображаются значения полей объекта данного класса. На переопределение родительского метода ToString указывает модификатор метода override.
Класс Found закрыл свои поля для клиентов, но открыл для потомков, снабдив их модификатором доступа protected.
Создадим теперь класс Derived - потомка класса Found. В простейшем случае объявление класса может выглядеть так:
public class Derived:Found
{
}
Тело класса Derived пусто, но это вовсе не значит, что объекты этого класса не имеют полей и методов: они "являются" объектами класса Found, наследуя все его поля и методы (кроме конструктора) и поэтому могут делать все, что могут делать объекты родительского класса.
Вот пример работы с объектами родительского и производного класса:
public void TestFoundDerived()
{
Found bs = new Found ("father", 777);
Console.WriteLine("Объект bs вызывает методы базового
класса");
bs.VirtMethod();
bs.NonVirtMethod();
bs.Analysis();
bs.Work();
Derived der = new Derived();
Console.WriteLine("Объект der вызывает методы класса
потомка");
der.VirtMethod();
der.NonVirtMethod();
der.Analysis();
der.Work();
}
Результаты работы этой процедуры показаны на рис. 18.2.
Рис. 18.2. Объект потомка наследует поля и методы родителя
В чем отличие работы объектов bs и der? Поскольку класс-потомок Derived ничего самостоятельно не определял, то он наследовал все поля и методы у своего родителя, за исключением конструкторов. У этого класса имеется собственный конструктор без аргументов, задаваемый по умолчанию. При создании объекта der вызывался его собственный конструктор по умолчанию, инициализирующий поля класса значениями по умолчанию. Об особенностях работы конструкторов потомков скажу чуть позже, сейчас же упомяну лишь, что конструктор по умолчанию потомка вызывает конструктор без аргументов своего родителя, поэтому для успеха работы родитель должен иметь такой конструктор. Заметьте, поскольку родитель не знает, какие у него могут быть потомки, то желательно конструктор без аргументов включать в число конструкторов класса, как это сделано для класса Found.
Yandex.RTB R-A-252273-3- 1. Лекция: Visual Studio .Net, Framework .Net
- Открытость
- Модульность
- Виртуальная машина
- Дизассемблер и ассемблер
- Метаданные
- Сборщик мусора - Garbage Collector - и управление памятью
- Исключительные ситуации
- События
- Общие спецификации и совместимые модули
- 2. Лекция: Язык c# и первые проекты
- Создание c#
- Виды проектов
- Консольный проект
- Windows-проект
- Начало начал - точка "большого взрыва"
- Выполнение проекта по умолчанию после "большого взрыва"
- Проект WindowsHello
- Общий взгляд
- Система типов
- Типы или классы? и типы, и классы
- Семантика присваивания
- Преобразование к типу object
- Примеры преобразований
- Семантика присваивания. Преобразования между ссылочными и значимыми типами
- Операции "упаковать" и "распаковать" (boxing и unboxing).
- 4. Лекция: Преобразования типов
- Где, как и когда выполняются преобразования типов?
- Преобразования ссылочных типов
- Преобразования типов в выражениях
- Преобразования внутри арифметического типа
- Преобразования и класс Convert
- Проверяемые преобразования
- Исключения и охраняемые блоки. Первое знакомство
- Опасные вычисления в охраняемых проверяемых блоках
- Опасные вычисления в охраняемых непроверяемых блоках
- Опасные преобразования и методы класса Convert
- 5. Лекция: Переменные и выражения
- Объявление переменных
- Время жизни и область видимости переменных
- Глобальные переменные уровня модуля. Существуют ли они в c#?
- Int X,y; //координаты точки
- Локальные переменные
- Глобальные переменные уровня процедуры. Существуют ли?
- Константы
- Выражения
- Приоритет и порядок выполнения операций
- Перегрузка операций
- Операции sizeof и typeof
- Как получить подробную информацию о классе?
- Статические поля и методы арифметических классов
- Логические операции
- Условное выражение
- Операция приведения к типу
- Присваивание
- Специальные случаи присваивания
- Определенное присваивание
- Еще раз о семантике присваивания
- Рассмотрим объявления:
- Класс Math и его функции
- Класс Random и его функции
- Блок или составной оператор
- If(выражение_1) оператор_1
- If(выражение1) if(выражение2) if(выражение3) ...
- Оператор switch
- Операторы break и continue
- Циклы While
- Цикл foreach
- Процедуры и функции - функциональные модули
- Процедуры и функции - методы класса
- Процедуры и функции. Отличия
- Описание методов (процедур и функций). Синтаксис
- Список формальных аргументов
- Тело метода
- Вызов метода. Синтаксис
- О соответствии списков формальных и фактических аргументов
- Вызов метода. Семантика
- Поля класса или функции без аргументов?
- Пример: две версии класса Account
- Функции с побочным эффектом
- Методы. Перегрузка
- 10. Лекция: Корректность методов. Рекурсия
- Корректность методов
- Инварианты и варианты цикла
- Рекурсия
- Рекурсивное решение задачи "Ханойские башни"
- Быстрая сортировка Хоара
- 11. Лекция: Массивы языка c#
- Общий взгляд
- Динамические массивы
- Многомерные массивы
- Массивы массивов
- Процедуры и массивы
- Класс Array
- Массивы как коллекции
- Сортировка и поиск. Статические методы класса Array
- Сводка свойств и методов класса Array
- Класс Object и массивы
- Массивы объектов
- Массивы. Семантика присваивания
- Общий взгляд
- Класс char[] - массив символов
- Операции над строками
- Строковые константы
- Неизменяемый класс string
- Статические свойства и методы класса String
- Метод Format
- Методы Join и Split
- Динамические методы класса String
- Операции над строками
- Основные методы
- Емкость буфера
- Пространство имен RegularExpression и классы регулярных выражений
- Немного теории
- Синтаксис регулярных выражений
- Классы Match и MatchCollection
- Классы Group и GroupCollection
- Пример "чет и нечет"
- Пример "око и рококо"
- Пример "кок и кук"
- Пример "обратные ссылки"
- Пример "Дом Джека"
- Пример "Атрибуты"
- 16. Лекция: Классы
- Синтаксис класса
- Поля класса
- Доступ к полям
- Методы-свойства
- Индексаторы
- Константы
- Конструкторы класса
- Деструкторы класса
- Проектирование класса Rational
- Методы класса Rational
- Закрытый метод нод
- Операции над рациональными числами
- Константы класса Rational
- Развернутые и ссылочные типы
- Классы и структуры
- Класс Rational или структура Rational
- Встроенные структуры
- Еще раз о двух семантиках присваивания
- Перечисления
- Персоны и профессии
- 18. Лекция: Отношения между классами. Клиенты и наследники
- Отношения между классами
- Отношения "является" и "имеет"
- Отношение вложенности
- Расширение определения клиента класса
- Отношения между клиентами и поставщиками
- Сам себе клиент
- Наследование
- Добавление полей потомком
- Конструкторы родителей и потомков
- Добавление методов и изменение методов родителя
- Статический контроль типов и динамическое связывание
- Три механизма, обеспечивающие полиморфизм
- Пример работы с полиморфным семейством классов
- Абстрактные классы
- Классы без потомков
- Преобразование к классу интерфейса
- Наследование от общего предка
- Клонирование и интерфейс iCloneable
- Сериализация объектов
- Класс с атрибутом сериализации
- Интерфейс iSerializable
- 20. Лекция: Функциональный тип в c#. Делегаты
- Как определяется функциональный тип и как появляются его экземпляры
- Функции высших порядков
- Вычисление интеграла
- Построение программных систем методом "раскрутки". Функции обратного вызова
- Наследование и полиморфизм - альтернатива обратному вызову
- Делегаты как свойства
- Операции над делегатами. Класс Delegate
- Пример "Плохая служба"
- 21. Лекция: События
- Классы с событиями
- Класс sender. Как объявляются события?
- Делегаты и события
- Как зажигаются события
- Классы receiver. Как обрабатываются события
- Классы с событиями, допустимые в каркасе .Net Framework
- Пример "Списки с событиями"
- Класс sender
- Классы receiver
- Переопределение значений аргументов события
- Классы с большим числом событий
- Проект "Город и его службы"
- 22. Лекция: Универсальность. Классы с родовыми параметрами
- Наследование и универсальность
- Синтаксис универсального класса
- Класс с универсальными методами
- Два основных механизма объектной технологии
- Стек. От абстрактного, универсального класса к конкретным версиям
- Ограниченная универсальность
- Синтаксис ограничений
- Список с возможностью поиска элементов по ключу
- Как справиться с арифметикой
- Родовое порождение класса. Предложение using
- Универсальные делегаты
- Framework .Net и универсальность
- 23. Лекция: Отладка и обработка исключительных ситуаций
- Корректность и устойчивость программных систем
- Жизненный цикл программной системы
- Искусство отладки
- Отладочная печать и условная компиляция
- Классы Debug и Trace
- Метод Флойда и утверждения Assert
- Выбрасывание исключений. Создание объектов Exception
- If !MyMethod(){// обработка ошибки}
- Параллельная работа обработчиков исключений
- Блок finally
- Класс Exception
- Организация интерфейса
- Форма и элементы управления
- Взаимодействие форм
- Модальные и немодальные формы
- Передача информации между формами
- Шаблон формы для работы с классом
- Наследование форм
- Два наследника формы TwoLists
- Огранизация меню в формах
- Создание меню в режиме проектирования
- Классы меню
- Создание инструментальной панели с командными кнопками
- Методы класса Graphics
- Класс Pen
- Класс Brush
- Событие Paint
- Кисти и краски
- 25. Лекция: Финальный проект
- Абстрактный класс Figure
- Класс Circle
- Список с курсором. Динамические структуры данных
- Классы элементов списка
- Организация интерфейса