Процедурное и объектно-ориентированное программирование:
Visual C++ и Delphi позволяют писать программа как процедурным методом, так и объектно-ориентированным (ООП). В чём разница, и какой метод лучше? Многие считают, что это ООП. А некоторые утверждают, что процедурный лучше. Я однозначного ответа дать не могу. Но рассмотреть эти методы обязан.
Процедурный метод появился где-то в семидесятые годы, когда мои родители даже не встретились. Он пришёл на замену старым методам, когда код был сплошной и переходы осуществлялись только по меткам. С приходом нового метода появилось много перспектив и многие восприняли его очень даже хорошо. Но нашлись люди, которые ругали этот метод, потому что код получаемый компиляторами С и Паскаль был медленней чем у Ассемблера. А программисты С и Паскаля ругали Ассемблер за то, что он неудобный и приходится писать очень много кода, когда в языках высокого уровня килобайт кода на Ассемблере заменяется одним оператором.
На мой взгляд, все доводы были верными, но время диктовало свои законы. Рынок программ был пустым и требовалось его заполнять с большой скоростью. Паскаль и С позволяют писать программы быстрее чем Ассемблер, поэтому этим программистам удалось выжить. А все кто программировал на чистом Ассемблере разделились на три части. Первая нашла себе достойную работу. Вторая стала писать модули, которые потом использовались в С и Паскале, потому что спрос на программистов на чистом Ассемблере резко упал. Третья перешла на С и Паскаль или просто бросила занятие программированием. Как не странно, но по некоторым данным третья часть самая большая.
Почему же так резко упал спрос на программистов языка Ассемблер? Это связано с тем, что рынок программ написанных на чистом Ассемблере уменьшился. На ассемблере пишут только вставки к играм, компиляторам и некоторым драйверам. Всё пользовательское программное обеспечение, которое занимает большую часть, пишется на языках высокого уровня.
Такая же история повторяется и с ООП. Процедурный язык вымирает. Его используют только производители игр и производители драйверов. Всё остальное постепенно переходит на ООП. Даже если посмотреть на твой Windows, то можно увидеть, что Windows 95 был на 90% процедурным, а Windows 2000 уже на 60% объектный.
Что же скрывается под процедурным и ООП? При процедурном программировании весь код разбивается на куски (процедуры и функции) которые образуют в целом полноценный код. Отдельная процедура не может существовать самостоятельно, она только составляющая часть все программы.
В ООП используется более общее понятие - объекты. Каждый объект это полноценный код, который имеет свои методы, свойства и события.
Методы - это процедуры и функции объекта.
Свойства - отражают состояние объекта.
События - объекты могут порождать события для информирования других о происходящих внутри объекта действиях.
ООП - это улучшенный процедурный метод. Да, он немного медленней работает, но он позволяет разрабатывать программы ещё быстрее и удобнее. В объектно-ориентированном коде намного легче разобраться и им удобнее управлять когда вы создаёте большой проект.
Рис 1. Иерархия гаража
Одно из величайших достижений в ООП - наследование. Рассмотрим пример. Вы написали объект - "гараж". Теперь вам нужно написать объект "дом". Гараж - это грубо говоря однокомнатный дом. Оба эти здания обладают одинаковыми свойствами - стены, пол, потолок и т.д. Поэтому желательно взять за основу гараж и доделать его до дома. Для этого ты создаёшь новый объект "Дом" и пишешь, что он происходит от "Гаража". Твой новый объект сразу примет все свойства гаража. Это значит, что у тебя уже будут стены, пол и потолок, и остается добавить только интерьер. Теперь у тебя будет уже два объекта: гараж и дом. Можно ещё создать будку для собаки. Для этого снова создаём объект "Будка" который происходит от "Гаража" (можешь произвести от "дома", чтобы в будке у собаки был интерьер :)). Нужно только уменьшить размер гаража и он превратится в будку. В итоге у тебя получается древовидная иерархия наследования свойств. На рис. 1 я показал примерную иерархию наших объектов.
Рис 2. Иерархия Delphi
Точно такой же метод наследования принят и в объектно-ориентированных языках. На рисунке 2. Я показал небольшую иерархию взятую из Delphi. Как видно из рисунка, все объекты происходят от TObject. Это базовый объект, который реализует основные свойства и методы. От него происходит TPersistent и TThread. Это только на моём рисунке. В реальности, от TObject происходит намного больше объектов и все они знают о его свойствах и методах и наследуют их себе.
Есть ещё один прикол, который очень удобен в ООП - полиморфизм. Что это за утка? Представим, что у гаража дверь открывается вверх, а у дома должны открываться в сторону. Дом происходит от гаража, поэтому у него дверь будет открываться тоже вверх. Как же тогда быть? Ты просто должен переписать у дома процедуру отвечающую за открытие двери. Тогда твой дом получит все свойства гаража, но за открывание двери подставит свою процедуру. Что-то подобное и есть полиморфизм, когда объекты разных иерархий по разному реагируют на одно и тоже событие.
Для того, чтобы можно было изменить процедуру отвечающую за открывание двери, она должна быть объявлена у гаража, как «виртуальная» (virtual). Виртуальная процедура говорит о том, что в порождённом объекте она может быть заменена.
И это ещё не всё. В гараже у нас стены голые, а в доме мы хотим повесит на них картины. Для реализации этого в ООП есть оболденная штука, как вызов метода предка. Рассмотрим пример:
Процедура отвечающая за создание стен у гаража.
Начало
Создать стены
Конец
Процедура отвечающая за создание стен у дома.
Начало
Вызвать объект предка.
Повесить на стены картины.
Конец
В процедуре отвечающей за создание стен у гаража мы создаём стены. У дома тоже есть такая процедура, т.е. мы её переопределяем. На первый взгляд процедура гаража должна пропасть и у дома придётся снова создавать стены, но это не так. Нужно просто вызвать объект предка (тогда создадутся стены), а потом спокойно вешать на стены картины. В Delphi для вызова процедуры предка используется ключевое слово inherited. Если нужно передать параметры, то нужно писать inherited Имя процедуры(параметр1, параметр2 …). Пример: