Читаем Рефакторинг. Зачем? полностью

Это была реализация классов, а тут реализация базовой функции HitTest, которая должна проверить все наши объекты:

var

Circles: array of TCircle;

Rectangles: array of TRectangle;

function HitTest(X, Y: Integer): Boolean;

var

I: Integer;

begin

Result:= False;

for I:= 0 to Length(Rectangles) — 1 do

begin

Result:= Rectangles[I].HitTest(X, Y);

if Result then

Exit;

end;

for I:= 0 to Length(Circles) — 1 do

begin

Result:= Circles[I].HitTest(X, Y);

if Result then

Exit;

end;

end;

Не слишком компактно получилось. А теперь представим, что разных типов примитивов у нас десятки и даже сотни. Получается для каждого нужен свой массив, и свой цикл для функции HitTest? Есть способ сделать проще, можно применить наследование.

В чём тут смысл? Вместо нескольких массивов для каждого графического примитива отдельно, мы заводим класс, который описывает графический примитив, назовём его, например, TShape. Далее мы хотим хранить все наши примитивы, независимо от их типа в массиве «Shapes: array of TShape». Но так просто у нас это не получится, компилятор ругнётся, что типы не совместимы.

Для того, чтобы мы смогли положить наши прямоугольники и круги в массив TShape, нам надо поменять их наследование. Заменим TObject на TShape в объявлении класса:

type

TShape = class(TObject)

end;

TCircle = class(TShape)

public

…..

end;

TRectangle = class(TShape)

public

…..

end;

Теперь наш круг одновременно и круг и графический примитив, равно как и в действительности. То же самое можно сказать и о квадрате. Что это значит с точки зрения программирования? То, что класс TCircle, наследник класса TShape можно использовать везде, где можно использовать класс TShape. Более того, все переменные и методы класса TShape (кроме private) будут также доступны в классе TCircle.

Не буду сильно углубляться в теорию, всё–таки я предпочитаю объяснять на примерах, поэтому сразу перейдём к тому как изменится наша функция с попмощью этого нехитрого преобразования:

var

Shapes: array of TShape;

function HitTest(X, Y: Integer): Boolean;

var

I: Integer;

begin

Result:= False;

for I:= 0 to Length(Shapes) — 1 do

begin

if Shapes[I] is TCircle then

Result:= (Shapes[I] as TCircle).HitTest(X, Y)

else if Shapes[I] is TRectangle then

Result:= (Shapes[I] as TRectangle).HitTest(X, Y)

if Result then

Exit;

end;

end;

На самом деле тоже не очень красиво. Приходится для каждого примитива делать проверку, поддерживает–ли он нужный нам тип (оператор is) и осуществлять приведение типов (оператор as). Операторы is и as предназначены для работы только с объектами и не работают с простыми типами. Подробнее о них можно прочитать в документации.

Чтобы оценить мощь наследования нам остался всего один шаг. В класс TShape добавим строку «function HitTest(X, Y: Integer): Boolean; virtual; abstract;”, а в классы TCircle и TRectangle добавим после аналогичных строчек ключевое слово override:

type

TShape = class(TObject)

public

function HitTest(X, Y: Integer): Boolean; virtual; abstract;

end;

TCircle = class(TShape)

public

 …..

function HitTest(X, Y: Integer): Boolean; override;

end;

TRectangle = class(TShape)

public

…..

function HitTest(X, Y: Integer): Boolean; override;

end;

Что это означает? Мы как бы говорим, что класс TShape в принципе может проверить, попали в него координаты мыши или нет, но конкретная реализация зависит от того, какой именно примитив используется. То есть абстрактно функциональность есть, но её реализация должна быть переопределена в классах потомках.

Нашу многострадальную функцию теперь можно переписать так:

var

Shapes: array of TShape;

function HitTest(X, Y: Integer): Boolean;

var

I: Integer;

begin

Result:= False;

for I:= 0 to Length(Shapes) — 1 do

begin

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных