Партнерка на США и Канаду по недвижимости, выплаты в крипто
- 30% recurring commission
- Выплаты в USDT
- Вывод каждую неделю
- Комиссия до 5 лет за каждого referral
Вызов не перекрытого абстрактного метода (т. е. помеченного директивой abstract) дает диагностику ошибки. Абстрактные методы используются на начальном уровне описания иерархии, а такая диагностика помогает при отладке программы находить потомки, в которых программист забыл перекрыть необходимые методы.
Пример использования виртуальных и абстрактных методов:
type
tField=
class function GetData:string;virtual;abstract; {нужна для работы
ShowData1}
tStringField=
class(tField)
fData:string;
function GetData:string;override;{перекрыли абстрактный метод}
end;
tIntegerField=
class(Field)
fData:Integer;
function GetData:string;override; {то же}
end;
...
реализация перекрывающих методов
function tStringField. GetData:string;
begin
GetData:=fData; {присваивание строкового поля}
end;
function tIntegerField. GetData:string;
begin
GetData:=IntToStr(fData); {преобразование из целого в строку}
end;
...
процедура, которая работает для разных типов полей
procedure ShowData(aField:tField);
begin
Form1.Label1.Caption:=aField. GetData;{вызов метода, который для
класса tField абстрактный}
end;
Надо отметить, что на этапе написания процедуры ShowData мы используем алгоритм для экземпляра класса, в котором описан наш абстрактный метод. Такой класс логично называть абстрактным и считать, что экземпляров данного класса быть не может. На деле, вместо экземпляров абстрактного класса будут подставляться экземпляры классов-потомков, в которых все абстрактные методы перекрыты. А формальное использование объекта из прародительского класса дает возможность писать единый алгоритм для всех классов-потомков разветвляющейся иерархии с разными типами аналогичных по смыслу полей в каждой ветви иерархии.
Особенность нового синтаксиса для объектов — то, что динамически созданный объект как параметр можно передавать как по значению (см. ShowData), так и по имени (см. далее ShowData1):
procedure ShowData1(var aField:tField);
begin
...
end.
При этом в случае передачи по значению котируется только указатель на объект, но не его тело. В Object Pascal, в отличие от C++, нет понятия "конструктора копии", и при необходимости скопировать тело объекта надо просто задать метод объекта, который занимается его копированием.
4.12. Области видимости объектов.
В Delphi существуют зарезервированные слова public ("общие"), protected ("защищенные") и private ("личные") для определения специальных правил видимости областей кода в объектах. Кроме того, для работы в среде Delphi используется еще зарезервированное слово published ("опубликованные"), являющееся вариантом public. Начиная с Delphi 3.0 при описании класса поля, свойства и методы должны располагаться в области, помеченной как published, public, protected и private.
Поля, свойства и методы доступны:
public, published — всем и везде, в том числе в других модулях;
protected — только в описании методов в классах потомков (в том числе в других модулях);
private — только в процедурах и функциях модуля, где описывается данный класс, а также в методах классов потомков, определенных внутри этого модуля.
Разновидностью public является published. "Опубликованные" поля, методы и свойства доступны в интерфейсе визуального проектирования Delphi (в инспекторе объектов) на стадии разработки. В первых версиях Delphi действовало правило, что если в описании класса были опущены ключевые слова для определения правил видимости, считалось, что соответствующие методы, поля и свойства published. Начиная с Delphi 3.0 область видимости объекта "published" также должна быть явно описана. Т. е. во всех примерах, где мы работали с классами, надо поставить директиву public или published перед описанием полей и методов объекта. Например:
tMyObj1=class(tObj1)
...
end;
заменить на
tMyObj1=class(tObj1)
public
...
end;
Пример правил видимости внутри модуля:
unit vis1;
interface
type
tObj1=
class
public
procedure MyPublicMethod;
...
protected
procedure MyProtectedMethod;
...
private
procedure MyPrivateMethod;
...
end;
procedure MyProc1; {процедура, видимая в других модулях}
...
секция реализации
implementation
... {реализация tObj1.MyPublicMethod, tObj1.MyProtectedMethod,
tObj1.MyPrivateMethod}
...
...
var aObj1:tObj1;
procedure MyProc1;
begin
aObj1:=tObj1.Create;
aObj1.MyPublicMethod; {можно}
{aObj1.MyProtectedMethod; - нельзя, т. к. не описание метода в
классе–наследнике}
aObj1.MyPrivateMethod; {можно, т. к. тот же модуль}
aObj1.Free; {то же, что Destroy, но с проверкой на nil}
end; {/MyProc1}
end. {/implementation}
Правила видимости в другом модуле:
unit vis2;
interface
uses vis1;
type
tObj2=
class(tObj1)
procedure MethodOfNewClass; {определение метода в потомке}
end;
procedure MyProc2; {процедура, видимая в других модулях}
секция реализации
implementation
procedure tObj2.MethodOfNewClass;
begin
MyPublicMethod; {можно, т. к. Public метод}
MyProtectedMethod; {можно, т. к. описание метода в
классе - наследнике}
{MyPrivateMethod; - нельзя, т. к. другой модуль}
end;
var aObj2:tObj2; {реализация}
procedure MyProc2;
begin
aObj2:=tObj2.Create;
aObj2.MyPublicMethod; {можно, т. к. public}
{aObj2.MyProtectedMethod; - нельзя, т. к. не описание метода
в классе - наследнике}
{aObj2.MyPrivateMethod; - нельзя, т. к. другой модуль}
aObj2.Free;
end;
end.
При описании класса-наследника можно переносить методы и свойства из одной области видимости в другую путем их простого упоминания, без переписывания реализации и сигнатуры:
type
tObj1=
class
private
fMyData:Real;
protected
function GetMyData:Real;
property MyData:Real
read GetMyData;
...
end{/class};
tObj2=
class(tObj1)
public
property MyData;
...
end{/class};
Замечание:
1) Из областей private в потомках в других модулях ничего достать, естественно, нельзя, хотя соответствующие поля и методы наследуются.
2) Иногда удобно перемещать поля или методы потомков из видимых областей в protected или private, иногда — наоборот (если это допустимо правилами прозрачности).
4.13. Обработка исключительных ситуаций.
Во время работы программы часто встречаются исключительные ситуации: деление на 0, отсутствие места на диске или попытка писать на защищенную для записи дискету, ошибочный символ при вводе (например, буква вместо цифры). В современных языках программирования для таких случаев предусмотрены специальные средства — обработчики исключительных ситуаций. В Delphi имеются 2 типа так называемых защищенных блоков кода:
1)try...finally...end;
2)try...except...end;
1) try...finally...end: если исключительных ситуаций не было, операторы в блоке try выполняются в обычном порядке, после чего выполняются операторы в блоке после finally. Если же возникла исключительная ситуация в блоке "try", выполнение блока прерывается, и сразу выполняется блок "finally" (его обычно используют для высвобождения ресурсов, и поэтому часто называют блоком "очистки кода"). Специальных операторов для этого типа обработки нет. Отличие кода внутри блока finally...end от кода, стоящего после этого end, возникает только при наличии внутри блока try операторов break или exit, т. к. в этом случае независимо от их срабатывания или несрабатывания сначала происходит выполнение блока очистки кода.
2) try...except...end: если исключений не было, выполняется только блок try. Если же возникла исключительная ситуация в блоке try, то обычная последовательность прекращается, и управление для обработки этой операции сразу передается в блок "except" со специальным синтаксисом:
try
...
except
on MyException1 do...{оператор1};
on MyException2 do...{оператор2}; ...
else {обычно отсутствует; не рекомендуется использовать}
MyOtherException {оператор обработки остальных исключений}
end{/except};
Исключительные ситуации являются классами-потомками объектного типа Exception=class(tObject) из модуля SysUtils и либо предопределены в системе (существуют исключительные ситуации: ZeroDivBy для операций с "плавающей запятой", DivByZero для целочисленных операций, InvalidGraphic и т. д.), либо описываются пользователем как потомки Exception (или его потомков).
Если ошибки не было, блок except не выполняется. Если ошибка была, выполняется блок except, после чего управление обратно в try не передается. При этом ищется первое соответствие исключения обработчику. Так, если возникла исключительная ситуация типа MyException1 (предопределенная или определенная в программе), то после выполнения оператора1 будет произведен выход из блока try...except...end без проверки на соответствие другим типам исключений.
По правилу совместимости типов исключительная ситуация типа-потомка всегда может быть обработана как исключение прародительского типа. Поэтому порядок следования обработчиков в блоке except имеет большое значение: обработчик исключения более общего типа следует писать всегда после обработчика для его типа-потомка, иначе обработчик потомка никогда не будет вызван.
Пример обработки исключений:
procedure MyETest(var X, Y,Z:real);
begin
try
Z:=sqrt(X/Y);
except
on EZeroDivide do messageBox('Деление на ноль',’Y’,mb_Ok);
on EInvalidOp do messageBox('Корень из отрицательного числа!',
‘Y’,mb_Ok);
end{/except};
end;
Если бы мы поставили строку EInvalidOp перед EZeroDivide..., то при делении на нуль обработчик для EInvalidOp перехватывал бы управление, и обработчик для EZeroDivide никогда бы не срабатывал.
Во время обработки исключительной ситуации некого типа создается объект-исключение соответствующего типа. Обычно имени типа исключения бывает достаточно, и объект-исключение остается без имени. Но при необходимости исключение может быть поименовано в блоке on..do, если в блоке do нужен доступ к полям объекта:
...
on EZD:EZeroDivide do EZD. message:='Деление на ноль. Проверьте
данные';
Таким образом, можно не только заменять, но и переопределять стандартные обработчики исключений. Например, в файле проекта (расширение. dpr — сокращение от Delphi project) можно сделать следующую обработку исключений:
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |


