Читать «Рефакторинг. Зачем?» онлайн - страница 11
DarkGoodWIN
LineLength:= Sqrt(Sqr(X2 — X1) + Sqr(Y2 — Y1));
LengthCalculated:= True;
end;
Result:= LineLength;
end;
procedure TLine. SetX1(const Value: Integer);
begin
LengthCalculated:= False;
FX1:= Value;
end;
procedure TLine. SetX2(const Value: Integer);
begin
LengthCalculated:= False;
FX2:= Value;
end;
procedure TLine. SetY1(const Value: Integer);
begin
LengthCalculated:= False;
FY1:= Value;
end;
procedure TLine. SetY2(const Value: Integer);
begin
LengthCalculated:= False;
FY2:= Value;
end;
И так, что мы сделали. Мы добавили полям X1, Y1, X2, Y2 префик «F» и перенесли в private секцию. Префикс «F» — это стандартный, исторически сложившийся префикс для обозначения приватного поля (сокращение от Field, поле). После этого напрямую менять значения координат снаружи класса стало невозможно.
Параллельно, также в private секции мы создали набор функций SetX1, SetY1, SetX2, SetY2 для корректной установки соответствующих значений. Помимо своих непосредственных обязанностей, они также сбрасывают флаг
Для доступа к приватным полям снаружи — предусмотрены свойства. Строка «property X1: Integer read FX1 write SetX1;” означает, что мы свойство X1, при чтении которого будет возвращаться значение
Таким образом, запись: «X:= Line. X1» эквивалентна записи «X:= Line. FX1», а запись «Line. X1:= X» эквивалентна записи «Line. SetX1(X)».
Наследование
Долго решался, прежде чем начать эту тему, обычно она достаточно сложна для понимания. Не уверен, что мне удасться уложиться в одну главу, но не беда. Главное быть последовательным. Давайте не уходить далеко от геометрических примитивов. Создадим два класса. Класс, описывающий круг и класс, описывающий прямоугольник:
type
TCircle = class(TObject)
public
X: Integer;
Y: Integer;
D: Integer;
end;
TRectangle = class(TObject)
public
X1: Integer;
Y1: Integer;
X2: Integer;
Y2: Integer;
end;
Круг вполне описывается координатами центра (X, Y) и диаметром (D), а прямоугольник — двумя точками (X1, Y1 и X2, Y2).
Допустим у нас есть программа для рисования кругов и прямоугольников. Каждый раз, когда мы рисуем новый круг, он кладётся в массив
Далее нам нужен код, который определит, находится–ли заданная координата внутри одного из нарисованных примитивов. Например, пользователь совершил клик мыши и нам нужно выделить приметив, если кликнули именно на него.
Заведём для этого в каждом классе функцию
type
TCircle = class(TObject)
public
X: Integer;
Y: Integer;
D: Integer;
function HitTest(aX, aY: Integer): Boolean;
end;
type
TRectangle = class(TObject)
public
X1: Integer;
Y1: Integer;
X2: Integer;
Y2: Integer;
function HitTest(X, Y: Integer): Boolean;