
ВОПР 1
Классы
Объявление класса
Класс — это тип данных, определяемый пользователем.
Класс должен быть объявлен до того, как будет объявлена хотя бы одна переменная этого класса. Т.е. класс не может объявляться внутри объявления переменной.
Синтаксис объявления класса следующий:
Туре <имя класса> = Class (<имя класса — родителя>) public {доступно всем}
<поля, методы, свойства, события> published {видны в Инспекторе Объекта и изменяемы} <поля, свойства>
protected {доступ только потомкам}
<поля, методы, свойства, события>
private (только в модуле}
<поля, методы, свойства, события>
end;
Имя класса может быть любым допустимым идентификатором. Но принято идентификаторы большинства классов начинать с символа «Т». Имя класса — родителя может не указываться. Тогда предполагается, что данный класс является непосредственным наследником TObject — наиболее общего из предопределенных классов.
type TMyClass = class end;
И
type TMyClass = class (TObject)
end;
Класс наследует поля, методы, свойства, события от своих предков и может отменять какие-то из этих элементов класса или вводить новые. Доступ к объявляемым элементам класса определяется тем, в каком разделе они объявлены.
Раздел public (открытый) предназначен для объявлений, которые доступны для внешнего использования. Это открытый интерфейс класса.
Раздел published (публикуемый) содержит открытые свойства, которые появляются в процессе проектирования на странице свойств Инспектора Объектов и которые, следовательно, пользователь может устанавливать в процессе проектирования.
Раздел private (закрытый), содержит объявления полей, процедур и функций, используемых только внутри данного класса.
Раздел protected (защищенный) содержит объявления, доступные только для потомков объявляемого класса.
Объявления полей выглядят так же, как объявления переменных или объявления полей в записях:
<имя поля>: <тип>;
Объявления методов в простейшем случае также не отличаются от обычных объявлений процедур и функций.
Свойства
Доступ к полям данных, как правило, должен осуществляться только через свойства, включающие методы чтения и записи полей. Поэтому поля целесообразно объявлять в разделе private — закрытом разделе класса. В редких случаях их можно помещать в protected — защищенном разделе класса, чтобы возможные потомки данного класса имели к ним доступ. Традиционно идентификаторы полей совпадают с именами соответствующих свойств, но с добавлением в качестве префикса символа 'F'.
Свойство объявляется оператором вида:
property <имя свойства>:<тип> read <имя поля или метода чтения> write <имя поля или метода записи> <директивы запоминания;
Если в разделах read или write этого объявления записано имя поля, значит предполагается прямое чтение или запись данных.
Если в разделе read записано имя метода чтения, то чтение будет осуществляться только функцией с этим именем. Функция чтения — это функция без параметра, возвращающее значение того типа, который объявлен для свойства. Имя функции чтения принято начинать с префикса Get, после которого следует имя свойства.
Если в разделе write записано имя метода записи, то запись будет осуществляться только процедурой с этим именем. Процедура записи — это процедура с одним параметром того типа, который объявлен для свойства. Имя процедуры записи принято начинать с префикса Set, после которого следует имя свойства.
Если раздел write отсутствует в объявлении свойства, значит это свойство только для чтения и пользователь не может задавать его значение.
Приведем пример. Пусть требуется объявить класс с именем MyC!ass, наследующий непосредственно TObject и имеющий свойство целого типа с именем А. Тогда объявление этого класса может иметь вид:
type
MyClass = class(TObject} private
FA: integer; protected
procedure SetA(Value: integer); {Процедура записи} published
property A:integer read FA write SetA default true; end;
Здесь вводится закрытое поле FA, объявляется защищенная функция SetA, используемая для записи значения этого поля, и вводится опубликованное свойство А, оперирующее этим полем. В объявлении свойства после ключевого слова read записано просто имя поля. Это означает, что функция чтения отсутствует и пользователь может читать непосредственно значение поля. После ключевого слова write следует ссылка на функцию записи SetA, с помощью которой будут записываться в поле А новые значения. В этой функции можно предусмотреть какие-то проверки допустимости вводимого значения А.
Вопр 2 Наследование
Любой класс жожет быть порожден от другого класса. Для этого при его объявлении указывается имя класса-родителя:
TChildClass = class(TParentClass)
Порожденный класс автоматически наследует поля, методы и свойства своего родителя и_может добавлять их новыми. Таким образом, принцип наследования обеспечивает поэтапное создание сложных классов и разработку собственных библиотек классов. Все классы Object Pascal порождены от единственного родителя - класса TObject. Этот класс не имеет полей и свойств, но включает в себя методы самого общего.назначения, обеспечивающие весь жизненный цикл любых объектов - от их создания до уничтожения. Программист не может создать класс, который не был бы дочерним классом TObject. Следующие два объявления идентичны:
TaClass = class (TObject) TaClass = class
Принцип наследования приводит к созданию ветвящегося дерева классов, постепенно разрастающегося при перемещении от TObject к его потомкам. Каждый потомок дополняет возможности своего родителя новыми и передает их своим потомкам.
Методы и их наследование, полиморфизм
При описании нового класса можно добавлять новые методы и свойства, оставляя методы и свойства родителей, а можно родительские методы и свойства переопределить или перегрузить.
Имеется четыре вида методов: статические, виртуальные, динамические и абстрактные.
По умолчанию все методы статические. Если в классе — наследнике переопределить такой метод (ввести новый метод с тем же именем), то для объектов этого класса новый метод отменит родительский. Если обращаться к объекту этого класса, то вызываться будет новый метод. Но если обратиться к объекту как к объекту родительского класса, то вызываться будет метод родителя.
Виртуальные и динамические методы не связаны с другими методами с тем же именем в классах — наследниках. Если в классах — наследниках эти методы перегружены, то при обращении к такому методу во время выполнения будет вызываться тот из методов с одинаковыми именами, который соответствует классу объекта, указанному при вызове. Например, если имеется базовый класс графических объектов TShape и ряд наследующих ему классов различных геометрических фигур, и если в каждом из этих классов определен свой виртуальный метод Draw, рисующий эту фигуру, то можно написать в программе:
var ShapeArray: array[1..10] of TShape;
for i:=l to 10 do ShapeArray[i].Draw;
В этом коде в массив ShapeArray могут помещаться объекты разных классов, наследующих TShape. В цикле for обращение к объектам производится как к объектам базового для них типа TShape. В этом случае для каждого объекта будет вызываться виртуальный метод Draw именно этого объекта. Такой подход, облегчающий работу с множеством родственных объектов, называется полиморфизмом.
При объявлении в классе виртуальных и динамических методов после точки с запятой, завершающей объявление метода, добавляются ключевые слова virtual или dynamic. Например:
type
TShape = class
procedure Draw; virtual;
end;
Чтобы перегрузить в классе — наследнике виртуальный метод, надо после его объявления поставит ключевое слово override. Например:
type
TRectangle = class(TShape)
procedure Draw; override;
end;
TEllipse = class (TShape)
procedure Draw; override; end;
Если в каком-то базовом классе метод был объявлен как виртуальный, то он остается виртуальным во всех классах — наследниках (в частности, и в наследниках классов наследников). Однако, обычно для облегчения понимания кодов перегруженные методы принято повторно объявлять виртуальными, чтобы была ясна их суть для тех, кто будет строить наследников данного класса. Например:
TEllipse = class (TShape)
procedure Draw; override; virtual;
end;
Описанным способом могут быть перегружены только виртуальные и динамические методы. Различие между динамическими и виртуальными методами невелико и относится к внутреннему механизму реализации их вызовов. Виртуальные методы эффективнее с точки зрения временных затрат, а динамические — с точки зрения затрат памяти. В целом виртуальные методы обеспечивают более эффективный механизм полиморфизма, а динамические более выгодны, если в базовом классе определено много перегружаемых методов и они одновременно используются многими объектами классов — наследников.
Абстрактный метод — это виртуальный или динамический метод, реализация которого не определена в том классе, в котором он объявлен. Предполагается, что этот метод будет перегружен в классах — наследниках. Только в тех классах, в которых он перегружен, его и можно вызывать.
Объявляется абстрактный метод с помощью ключевого слова abstract после слова virtual или dynamic. Например:
procedure DoSomething; virtual; abstract;
При реализации метода, переопределенного любым способом в классе — наследнике, можно вызывать метод класса — родителя. Для этого перед именем метода при его вызове записывается ключевое слово inherited. Например, оператор
inherited Create (...);
вызывает метод Create родителя.
Если записать слово inherited и после него не писать имя вызываемого метода, то будет вызываться наследуемый метод, совпадающий по имени с именем того метода, из которого он вызывается. Например, если в переопределяемом конструкторе встречается оператор
inherited; то будет вызван конструктор родительского класса.
ВОПР 3
Класс Exceptionявляется прямым потомком базового класса TObject. Вместе со своими потомками он предназначен для обработки исключительных ситуаций (исключений), возникающих при некорректных действиях программы: например, в случае деления на ноль, при попытке открыть несуществующий файл, при выходе за пределы выделенной области динамической памяти и т, п.
Защищенные блоки
Для обработки исключений в Object Pascal предусмотрен механизм защищенного блока:
Try
try
<операторы> <операторы> except finally
<обработчики исключений> <операторы>
elseend;
<операторы> end;
Защищенный блок начинается зарезервированным словом try (попытаться [выполнить]) и завершается словом end. Существует два типа защищенных блоков -except (исключить) и finally (в завершение), отличающихся способом обработки исключения.
В блоке except порядок выполнения операторов таков: сначала выполняются операторы секции try.. .except; если операторы выполнены без возникновения исключительной ситуации, работа защищенного блока на этом прекращается и управление получает оператор, стоящий за end; если при выполнении части try возникло исключение, управление получает соответствующий обработчик в секции except, а если таковой не найден - первый из операторов, стоящих за словом else.
В блоке finally операторы в секции finally...end получают управление всегда, независимо от того, возникло исключение в секции try.. .finally или нет. Если исключение возникло, все операторы в секции try.. .finally, стоящие за «виновником» исключения, пропускаются и управление получает первый оператор секции finally.. .end. Если исключения не было, этот оператор получает управление после выполнения последнего оператора секции try... finally.
Обработчики исключений в блоке except имеют такой синтаксис:
on <класс исключения> do <оператор>;
Здесь on, do - зарезервированные слова; <класс исключения> - класс обработки исключения; <оператор> - любой оператор Object Pascal, кроме оператора передачи управления goto на метку вне блока except.
Обратите внимание: имя класса служит своеобразным ключом выбора, а собственно обработка осуществляется оператором, стоящим за do (этот оператор может быть составным, так что обработка исключения может занимать произвольное количество операторов Object Pascal).
Поиск нужного обработчика осуществляется с начала списка вниз до тех пор, пока не встретится класс, способный обрабатывать исключение данного типа. Если подходящего класса не обнаружено, управление передается операторам, стоящим за словом else, а если таковых нет (часть else <операторы> может опускаться), выполняется умалчиваемая обработка исключения.
Защищенные блоки могут вкладываться друг в друга на неограниченную глубину, т. к. везде, где в предыдущих описаниях использовались <операторы> или <оператор>, могут использоваться любые операторы Object Pascal, в том числе и try...except или try...finally.
Класс Exception является родительским классом для всех классов-исключений. Этот класс объявляется в модуле SysUtils.
ВОПР 4