Вы находитесь на странице: 1из 34

Основы объектно-

ориентированного
программирования

Чернойван Василий Александрович


vchernoivan@gmail.com
http://chernoivan.ru/oop
Шаблоны
(Обобщенные типы)
Стек целых чисел
Что, если нам нужен стек из чисел
double или из IСommand ?

Copy & Paste!


Стек из объектов
Стек объектов

Небезопасен
- Требует приведения
- Можно “положить” в стек не-int
Иерархия наследования в C#
Стэк - шаблон
Шаблоны : конкретизация, UML
Шаблоны: ограничения
Шаблоны: ограничения
Ограничение Описание
where T: struct Параметр должен быть значимым типом

where T : class Параметр должен быть ссылочным типом –


классом, делегатом, интерфейсом

where T : new() Параметр должен иметь публичный


конструктор
where T : <Класс> Параметр должен быть унаследован от
класса <Класс>
where T : <Интерфейс> Параметр должен реализовать интерфейс
<Интерфейс>
where T : U Параметр T должен быть наследником
параметра U.
Шаблоны
● Шаблон для класса задает способ построения
отдельных классов (шаблон – «формочка» для
классов)
● В модели маркеры - “из”, “для”
● Кирпич из красной глины
● Кирпич из белой глины
● Шлакоблок
Шаблоны
● Новые классы получаются подстановкой
параметров во время компиляции
● Шаблоны можно наследовать, как обычные
классы
● Ограничения, накладываемые на классы-
параметры нужно явно указать, используя
ключевое слово where, которое «понимает»
отношения наследования и реализации, а также
наличие публичного конструктора
Шаблоны
● Можно определять шаблонные
классы, интерфейсы, делегаты, методы

● Параметры шаблона входят в


сигнатуру, т.е. можно переопределить
метод с одним именем и разными
параметрами-типами
Обработка ошибок
Что такое ошибки?

https://habrahabr.ru/post/266591/
https://thescene.com/watch/arstechnica/ho
w-the-stack-works-part-1
Как обрабатывать ошибки?

Класс vector и функцию Main пишут


разные люди в разное время
Как разработчик класса Vector «скажет»
разработчику функции Main2, что
последний использует класс Vector
неправильно?
- Завершить работу

- Вернуть значение «ошибка»

Стандартные процедурные способы

- Вернуть нормальное значение и сообщить об


ошибке посредством глобальной переменной
Недостатки процедурного подхода
- Вариант с завершением работы изначально
неприемлем в большинстве случаев
- Вариант с ошибочным значением не всегда
применим – очень сложно «угадать», какое
значение ошибочно, а какое нет
- Вариант с глобальной переменной нельзя
использовать в многопоточной среде
- Сложно «пробросить» подробности проблемы
в вызывающий код
- Программа быстро «пухнет» и становится
нечитаемой
- Чтобы отслеживать все ошибки, нужна
сильная воля и энтузиазм программиста, чего
чаще всего не бывает ☹
Обработка ошибок в ООП стиле:
Исключения
- Ошибки рассматриваются как абстракция –
особая ситуация, или исключение: Exception

- Язык С# предоставляет возможность сообщать


о том, что произошла ошибка — генерировать
или «бросать» (throw) исключения

- А также специальным образом эти ситуации


обрабатывать, или «ловить» (catch) исключения
Пример: «ловим» исключение
Исключения
- Механизм исключений позволяет явно
отделить код обработки ошибки от
основного кода программы

- Исключение - «аварийный» возврат из


метода вверх по стэку вызовов, до тех
пор, пока не встретится соотвествующий
блок catch

- Ключевое слово try начинает «слежку»


за возникшими исключениями, блок catch
обрабатывает их, на основании типа
Что сделал разработчик класса Vector?
«Отлов» исключений: продолжение
Исключения
• В блоке catch можно узнать подробности о
брошенном исключении, если создать объект-
исключение. А можно и не узнавать, если
объект не создавать.

• Блоков catch может быть несколько – по


одному на каждый тип исключений. Вызывается
всегда только один.

• Блоки catch «понимают» наследование


Блоки обработки базовых исключений должны
идти после обработки более
специализированных
Исключения
• Если полностью обработать исключение не
удается, его можно «бросить» дальше, в
надежде, что кто-то «выше» знает, что с ним
сделать.

• «Бросить» можно только объекты, которые


унаследованы от System.Excepton

• Исключения имеют много полезной


встроенной информации, такой как
сообщение, стэк вызовов или исходное
исключение
Когда нужно бросать исключения?
Общее правило:
- Если что-то идет не так и мы не знаем,
что с этим делать - бросаем исключение
- Если информации для обработки на
текущем уровне недостаточно, не ловим
исключение или бросаем заново из
блока catch
- Если у нас есть понимание, что
происходит, исключение нужно ловить и
обрабатывать
Стратегии использования
исключений
- Исключения только для ошибок
программирования

- Исключения как штатный механизм работы с


ошибками предметной области
Захват/освобождение ресурса
Захват ресурсов: finally
• Ключевое слово finally используется для
обозначения блока, который выполняется в
случае любого завершения предшествующего
блока try или try/catch

• Блок finally выполняется в т.ч. при выходе из


текущего метода с помощью оператора
return
Захват ресурсов: IDisposable
Захват ресурсов: IDisposable
Захват ресурсов: IDisposable
Захват ресурсов: IDisposable
• Если Ваш класс использует управляемые
(IDisposable) ресурсы, он тоже должен
реализовать интерфейс IDisposable
• Блок using позволяет в более компактной
форме передать семантику try / finally
• В одном блоке using можно использовать
сразу несколько ресурсов
• using создает свою собственную область
видимости и при выходе из нее
гарантированно вызывает IDisposable.Dispose
для каждого из аргументов
Спасибо за внимание

Вопросы?