Понятие объекта. Создание и уничтожение объектов. Свойства
Полезная статья? Пожалуйста, поставьте "+"
Алгоритмизация и программирование - Содержание
Чтобы использовать новый тип в программе, нужно, как минимум, определить
переменную этого типа. Переменная объектного типа называется
экземпляром типа или объектом:
var aMyObject: tMyClass;
До
введения понятия "класс” в языке Pascal существовала двусмысленность
определения "объект”, который мог обозначать и тип, и переменную этого
типа. Теперь существует четкая граница: класс - это описание, объект -
то, что создано в соответствии с этим описанием.
Создание и уничтожение объектов В
отличие от С++ и Turbo Pascal в Delphi объекты могут быть только
динамическими!!!. Это означает, что в приведенном выше примере
переменная aMyObject на самом деле является указателем, содержащем адрес
объекта.
Объект создается конструктором и уничтожается деструктором. aMyObject := tMyClass.Create; // // действия с созданным объектом // aMyObject.Destroy;
Следует
обратить внимание на то, что для создания объекта aMyObject вызывается
метод класса tMyClass.Create. Конструктор класса (и ряд других методов)
успешно работает и до создания объекта. Однако большинство обычных
методов (в частности все виртуальные и динамические методы). Вызывать до
инициализации объекта не следует.
В Delphi конструкторов у
класса может быть несколько. Общепринято называть конструктор Create, в
отличие от Turbo Pascal, где конструкторы назывались Init, и С++, в
котором имя конструктора совпадает с именем класса. Типичное название
деструктора - Destroy.
type tMyClass=class(tObject) fMyFiled: integer; Constructor Create; Destructor Destroy; function MyMethod: integer; end;
Для
уничтожения объекта в Delphi рекомендуется использовать не деструктор, а
метод Free, который первоначально проверяет указатель, и только затем
вызывает деструктор Destroy:
procedure tObject.Free;
До
передачи управления телу конструктора происходит собственно создание
объекта: под него отводится память, значения всех полей обнуляются.
Далее выполняется код конструктора, написанный программистом для
инициализации объектов данного класса. Таким образом, несмотря на то,
что синтаксис конструктора схож с вызовом процедуры (отсутствует
возвращаемое значение), на самом деле конструктор - это функция,
возвращающая созданный и проинициализированный объект.
Примечание.
Конструктор создает новый объект только в том случае, если перед его
именем указано имя класса. Если указать имя уже существующего объекта,
он поведет себя по-другому: не создаст новый объект, а только выполнит
код, содержащийся в теле конструктора.
Чтобы правильно
проинициализировать в создаваемом объекте поля, относящиеся к классу -
предку, нужно сразу же при входе в конструктор вызвать конструктор
предка при помощи зарезервированного слова inherited:
constructor tMyClass.Create; Begin inherited Create; // Код инициализации tMyClass End;
Как
правило, в коде программ, написанных на Delphi, практически не
встречается вызовов конструкторов и деструкторов. Дело в том, что любой
компонент, попавший при визуальном проектировании в приложение из
палитры компонентов, включается в определенную иерархию. Эта иерархия
замыкается на форме (класс tForm): для всех ее составных частей
конструкторы и деструкторы вызываются автоматически, незримо для
программиста. Кто создает и уничтожает формы? Это делает приложение
(объект с именем Application). В файле проекта (с расширением DPR) вы
можете увидеть вызовы метода Application.CreateForm, предназначенного
для этой цели.
Что касается объектов, создаваемых динамически
(во время выполнения программы), то здесь нужен явный вызов конструктора
и метода Free.
Свойства Как известно,
существует три основных принципа, составляющих суть
объектно-ориентированного программирования: инкапсуляция, наследование и
полиморфизм. Классическое правило объектно-ориентированного
программирования утверждает, что для обеспечения надежности нежелателен
прямой доступ к полям объекта: чтение и изменение их содержимого должно
осуществляться посредством вызова соответствующих методов. Это правило
называется инкапсуляцией (сокрытие данных). В старых реализациях ООП
(например в Turbo Pascal) эта мысль внедрялась только посредством
призывов и примеров в документации; в Delphi есть соответствующая
конструкция. Пользователь объекта в Delphi может быть полностью
отгорожен от полей объекта при помощи свойств.
Обычно свойство определяется тремя элементами: полем и двумя методами осуществляющими его чтение/запись: type tMyClass=class(tObject) function GetaProperty: tSomeType; procedure SetaProperty(Value: tSomeType); property aProperty: tSomeType read GetaProperty write SetaProperty; end;
В
данном примере доступ к значению свойства aProperty осуществляется
через вызовы методов GetaProperty и SetaProperty, однако в обращении к
этим методам в явном виде нет необходимости: достаточно написать
aMyObject.aProperty:=aValue; aVarable:= aMyObject.aProperty;
и
Delphi откомпилирует эти операторы в вызовы соответствующих методов. То
есть внешне свойство выглядит в точности как обычное поле, но за всяким
обращением к нему могут стоять вызовы необходимых программисту методов.
Например, если есть объект, представляющий собой квадрат на экране, и
его свойству "цвет” присваивается значение "белый”, то произойдет
немедленная прорисовка, приводящая реальный цвет на экране в
соответствие значению свойства.
В методах, устанавливающих
значения свойства, может производиться проверка значения на попадание в
заданный диапазон значений и вызов других процедур зависящих от вносимых
изменений. Если же потребности в специальных процедурах чтения/записи
нет, можно вместо имен методов применять имена полей.
tPropClass=class fValue: tSomeType; procedure SetValue(aValue: tSomeType); property Value:tSomeType read fValue write SetValue; End;
В этом примере поле fValue модифицируется при помощи метода SetValue, а читается напрямую.
Если свойство должно только читаться или только записываться, в его описании может присутствовать только соответствующий метод:
tReadOnlyClass=class property NotChanged:tSomeType read GetNotChanged; End;
В этом примере свойство доступно только для чтения. Попытка присвоить значение свойству NotChanged вызовет ошибку компиляции.
Свойствам можно присваивать значения по умолчанию. Для этого служит ключевое слово default:
Property Visible:boolean read fVisible write SetVisible default TRUE;
Это означает, что при запуске программы свойство будет установлено компилятором в TRUE.
Свойство может быть и векторным. В этом случае оно выглядит как массив:
Property Points[index:integer]:tPoint read GetPoint write SetPoint;
Для
векторного свойства необходимо описать не только тип элементов массива,
но также и тип индекса. После ключевых слов read и write должны идти
имена соответствующих методов. Использование здесь полей массивов
недопустимо. Метод, читающий значение векторного свойства, должен быть
описан как функция, возвращающая значение того же типа, что и элементы
свойства, и имеющая единственный параметр того же типа и с тем же
именем, что и индекс свойства:
function GetPoint(index:integer):tPoint;
Аналогично,
метод, помещающий значения в такое свойство, должен первым параметром
иметь индекс, а вторым - переменную нужного типа.
procedure SetPoint(index:integer; Value:tPoint);
У
векторных свойств есть еще одна важная особенность: некоторые классы в
Delphi (списки tList, наборы строк tStrings и т.д.) "построены” вокруг
одного основного векторного свойства. Основной метод такого класса дает
доступ к элементам некоторого массива, а все основные методы являются
как бы вспомогательными. Для упрощения работы с объектами подобного
класса можно описать подобное свойство с ключевым словом default:
type tMyList=class property list[Index:integer]:string read Getlist write Setlist; default; end;
Если у объекта есть такое свойство, его можно не упоминать, а ставить индекс в квадратных скобках сразу после имени объекта:
var MyList:tMyList Begin MyList.list[1]:=’First’; {Первый способ} MyList.[2]:=’Second’; {Первый способ} End;
Употребляя
ключевое слово default необходимо соблюдать осторожность, т.к. для
обычных и векторных свойств оно употребляется в разных значениях.
О
роли свойств в Delphi красноречиво говорит тот факт, что у всех
имеющихся в распоряжении программиста стандартных классов 100% полей
недоступны и заменены базирующимися на них свойствами. Того же правила
следует придерживаться и при разработке собственных классов.
|
Категория: Алгоритмизация и программирование | Добавил: Ni-Cd (10 Декабря 2011)
|
Просмотров: 2289
| Рейтинг: 0.0/0 |
Добавлять комментарии могут только зарегистрированные пользователи. [ Регистрация | Вход ]
|
|
Онлайн |
Онлайн всего: 1 Гостей: 1 Пользователей: 0 |
|
|