3 4 2 1
2 4 3 1
4 1 3 2
Здесь первый кандидат набирает сумму 10, второй – 8, третий – 7, четвертый – 5. Таким образом, побеждает четвертый кандидат в списке.
Количество кандидатов известно и равно пяти. Ваша программа принимает файл, каждая строка которого содержит 5 чисел – данные одного бюллетеня. Надо выдать список победителей голосования (одного или нескольких).
Глава 61
«Кубики» программиста (ООП)
А напоследок отведайте волшебного объектно-ориентированного программирования (ООП). Эта технология преобразила ремесло программиста, – так пройдем ли мимо?
Фокус-покус
Вначале дадим слово Паскалю. Если вы работаете в IDE Borland Pascal, введите и запустите следующую программку. Только убедитесь в том, что библиотечный файл «APP.TPU» доступен компилятору (обычно он находится в папке «UNITS», где собраны фирменные библиотечные модули).
{P_61_1 – демонстрация работы Turbo Vision }
uses App;
var A : TApplication;
begin
A.Init;
A.Run;
A.Done;
end.
Как это работает? – не спрашивайте, ведь программка очень проста, что ещё надо? После ее запуска вам откроется следующая картина (рис. 152).
Рис.152 – Окно программы MyApp
Неужто «сломалась» IDE? В самом деле, где меню и окно с текстом программы? Да и статусная строка совсем не та. Но мышка по-прежнему бегает, и клавиатура жива. Можно щелкнуть по слову «Exit» и выйти из программы, или сделать то же самое нажатием Alt+X. Да, друзья, вы наблюдаете действие той самой малюсенькой программки! Ее поведение чудесно, но возможности этим не исчерпаны. Своей мощью она обязана объектам из библиотеки Turbo Vision, на которой построена вся IDE Borland Pascal.
Вместо паяльника
Все восторгаются объектным программированием. А откуда оно взялось?
Представьте, что при покупке телевизора вместо работающего изделия вам вручают его схему и коробку с деталями. И предлагают собрать телевизор самому! Примерно в таком же положении находились когда-то и программисты. Используемые ими библиотеки хранили массу полезных процедур и функций, – своего рода «схемы» для сборки программ. А «деталями» были обрабатываемые данные. Программист распределял эти данные в программе, придавая им нужную структуру, применял к данным в надлежащем порядке процедуры и функции, отслеживая при этом влияние одних данных на другие. Работа эта сродни сборке телевизора! Плодовитость программистов и качество их изделий оставляли желать лучшего, ненадежные программы было трудно править, да и пользоваться ими было неудобно.
Так вернемся к телевизору; что нужно знать мне, его владельцу? Всего лишь несколько кнопок: включить, отключить, выбрать канал, настроить громкость. И все! Остальное пусть будет спрятано. Вот бы и в программировании добиться такого удобства! Изобретатели ООП стремились именно к этой цели – упростить работу со сложной совокупностью данных. Они догадались объединить в одно целое данные и процедуры, их обрабатывающие. Совокупность данных и процедур назвали объектом.
На первый взгляд объект похож на запись. Но, в отличие от записи, большинство данных и процедур объекта спрятано внутри и не видно за его пределами. Снаружи доступно лишь то, что интересует пользователя объекта, – в этом объект похож на модуль (или на собранный телевизор).
На трех китах
Основу ООП составляют три идеи, три «кита», а именно:
• инкапсуляция;
• наследование;
• полиморфизм.
Рассмотрим их в этом порядке.
Примечание. Для примеров этой главы настройте компилятор в режим, совместимый с Borland Pascal.
Инкапсуляция
Инкапсуляция – это объединение данных и обрабатывающих их процедур. Рассмотрим простой пример: построим объект для хранения и обработки информации о человеке. Человеку свойственны такие атрибуты как год рождения, имя и фамилия. Поставим цель упростить работу с этими атрибутами, – создадим объект, способный хранить и распечатывать эту информацию.
Объявление объекта
Объявление объекта похоже на объявление записи, с той разницей, что ключевое слово RECORD заменяют словом OBJECT. В Delphi и совместимом с ним режиме Free Pascal применяют ключевое слово CLASS. Итак, «застолбим» место хранения информации о человеке тремя полями, как это показано ниже.
type TPerson = object
mBearing : integer; { год рождения }
mName : string; { имя }
mFam : string; { фамилия }
end;
Здесь объявлен тип данных TPerson (персона), содержащий три поля с данными о человеке. Для распечатки данных учредим процедуру по имени Report. Но процедура эта особая! Её заголовок помещен внутрь описания объекта следующим образом:
type TPerson = object
mBearing : integer; { год рождения }
mName : string; { имя }
mFam : string; { фамилия }
procedure Report; { процедура распечатки объекта }
end;
Методы
Процедуры и функции, объявленные внутри объекта, называют методами объекта. Методы, как и поля, – неотъемлемая часть объекта. Но объявить метод недостаточно, надо создать и его тело или, как принято говорить, реализацию метода. Реализация – это подпрограмма (процедура или функция), которая от обычной подпрограммы отличается заголовком: там к имени метода добавляется приставка, указывающая тип объекта, которому принадлежит метод. Реализация метода Report будет очень простой.
procedure TPerson.Report;
begin
Writeln(mBearing:6, 'Фамилия: '+mFam:20, ' Имя: '+mName);
end;
Процедура распечатывает атрибуты человека. Но откуда она берет их? – эти данные не передаются через параметры, и не хранятся в глобальных переменных. Они объявлены как поля объекта, и этого достаточно, чтобы метод объекта получил доступ к ним.
Инициализация, конструктор
Поля объекта, как любые переменные, нуждаются в инициализации. Как проще осуществить её? Можно присвоить значения полям так, как это делается для записей.
var P : TPerson; { переменная-объект }
begin
P.mFam:=’Сидоров’;
P.mName:= ’Тимофей’;
end.
Но, когда полей много, вы забудете что-то – в этом слабость идеи. Куда надежней учредить особый метод для инициализации полей. Такой метод и назван особо – конструктор. Вместо слова PROCEDURE перед именем конструктора так и пишут: CONSTRUCTOR. Назвать конструктор можно как угодно, но по традиции ему дают имена Init (инициализировать) или Create (создать). Например, для нашего объекта объявить конструктор и реализовать его тело можно так:
type TPerson = object
{... }
{ заголовок конструктора внутри объекта }
constructor Init(aBearing: integer; const aName, aFam : string);