
- •Программирование и алгоритмические языки. Курс за третий семестр.
- •Введение в объектно-ориентированное программирование (ооп)
- •Идеологический обзор
- •Базовые принципы ооп
- •Наследование имён. Наследование значений.
- •Коллизия
- •Что такое имя процедуры?
- •Ооп как оперирование типами
- •Именование типов в c# Тип данных «класс»
- •Конструкторы и деструкторы
- •И нкапсуляция данных
- •Наследование (краткое введение)
- •Наследование реализации как уточнение семантики типа
- •Пополнение и переопределение методов Отношение пополнения интерфейса
- •Открытие реализации для проектирования классов - опция protected
- •Полиморфизм Полиморфизм как уточнение семантики типа переменной
- •Динамические методы как поддержка полиморфизма- опции static, virtual, override
- •Событийное программирование Обработка событий
- •Идея: Когда что-то вставляется, срабатывает некоторый предикат. Например, после вызывается команда проверки, каскадного удаления или какая-нибудь другая команда. Генераторы и приёмники сообщений
- •Событийное программирование нужно:
- •Событийный стиль в процедурном программировании - управление данными (на примере)
- •Событийное программирование в c# (delegate, event)
- •Введение в компонентное программирование
- •Объекты, реализующие интерфейсы
- •Частный случай общей проблемы взаимодействия программного обеспечения разных производителей на уровне исполняемого кода
- •Базовый интерфейс компонент
- •Проблема множественности иерархий
- •Коллизия имён
- •Коллизия реализации
- •«Симметричное» решение – агрегаты (декартовы произведения классов)
- •Множественное наследование
- •«Асимметричное» решение - именованные интерфейсы
- •Основные отличия интерфейса и абстрактного класса
- •Наследование интерфейса (компонентный подход)
- •Обработка исключений в ооп
- •Определение и генерация исключений в c#
- •Выбрасывание исключений
- •Захват исключения
- •Блок finally
- •Коды программ
Наследование (краткое введение)
Семантика uses в модульном программировании:
Нужно вспомнить понятие модифицированного тела процедуры. После неких синтаксических правок можно считать, что интерфейсные функции определены в том же модуле (в том смысле, что они определены и ими можно пользоваться).
Синтаксические правки заключаются в коллизии имён. Здесь под одним и тем же именем можно было определять разные сущности с одинаковым именем (процедуры, функции, константы, переменные).
Вставал вопрос: как разрешить коллизию?
Сначала родовое имя - имя модуля, а потом точка и название поля.
Наследование реализации как уточнение семантики типа
Наследование синтаксическое - добавление определения новых имён (компонентное программирование основано на нём).
Наследование- иерархия уточнения – разделение сложности при определении типов.
Определение типа - это постепенное уточнение типа (уточнять можно пополнением).
П
онятие
наследования – попытка определить
понятие подтипа или подкласса, где
подкласс- это наследник в смысле ООП.
Наследование имён - пополнение интерфейса. Наследование интерфейса отражает естественный ход программирования как добавление новых имён.
Пополнение и переопределение методов Отношение пополнения интерфейса
Рис. Наследование определений функций из первого модуля.
Замечание: интерфейс второго модуля более полный.
Наследование интерфейса отражает естественный ход программирования - добавление новых имён.
При этом возможны два случая:
- реализация не меняется (по умолчанию)
- реализация меняется - ссылается на предыдущую
(с точки зрения семантики это означает доопределение (уточнение) значения данного имени). Проще говоря, мы начинаем относиться к функциям как к переменным. Другими словами, тип становится изменяемым атрибутом (одной из характеристик переменной).
Пример: x:=x+1
Существует преобразование, являющееся неявным и естественным – низкая иерархия наследования (т.е. типы могут уточняться (конкретизироваться)). Подобное последовательное переопределение значений имён характерно не только для программирования, но и для любой классификации.
Разного рода иерархии нам нужны для классификации:
Животные
Рыбы Млекопитающие Птицы
Акула Карась Дельфин Слон Пингвин Петух
Пресмыкающиеся Насекомые
Динозавр Блоха
Это тривиальная классификация, а вернее её отсутствие, т.к. реальные классификации заглублённые. Это, фактически, напоминание о том, что иерархия существует и всякая наука начинается с систематизации знаний.
Синтаксис наследования:
При наследовании имена производного и базового классов разделяются двоеточием (:). Производный класс получает все поля, свойства и методы базового класса.
Class (Имя класса потомка): (Имя класса предка)
{
…
}
Пример: класс Bird (Птица) наследует класс Vertebrate (Позвоночное)
class Vertebrate // класс "Позвоночное животное"
{
public int NumberOfLegs;
public void Eat()
{
//код, заставляющий есть
}
}
class Bird : Vertebrate //расширяется класс путём добавления в конец его двоеточия и имени базового класса
{
public double Wingspan;
public void Fly()
{
//код, заставляющий летать
}
}
class Program
{//запускалка:
static void Main()
{
//так как tweety- это экземпляр объекта Bird, то он имеет методы и поля этого объекта
Bird tweety = new Bird();
tweety.Wingspan = 7.5; // tweety-название птички
tweety.Fly();
//т.к. класс Bird - производный по отношению к классу Vertebrate, все экземпляры Bird имеют поля и методы, определённые в классе Verteble
tweety.NumberOfLegs = 2;
tweety.Eat();
}
}
С точки зрения наследования все классы являются потомками класса cObject.
Таким образом, понятие наследования - это попытка определить понятие подтипа или подкласса. Всякого рода явные преобразования возможны, а средства явного преобразования типов есть. Грубо говоря, это схема «всё-во-всё». Реализация очевидна: всё рассматривается на уровне двоичных полей.