Компоненти на класа

Сайт на Delphi: ежедневни Delphi-новини, документация, статии, преглед, интервю, компютърен хумор.

Както вече споменахме, съставните части на даден клас често се наричат ​​негови членове.

Полетата са данни, капсулирани в клас. Полетата могат да бъдат от всякакъв тип, включително класове, например:

тип TMyClass = клас

Всеки обект получава уникален набор от полета, но набор от методи и свойства, общи за всички обекти от даден клас. Основният принцип на капсулирането изисква полетата да бъдат достъпни само чрез методи и свойства на класа. Въпреки това, в Delphi можете също да получите директен достъп до полета:

тип TMyClass - клас

Отбелязвам, че при конструирането на компоненти полетата обикновено се правят недостъпни за други кокласове и достъпът до тях се осъществява чрез методи и свойства на класа.

Класът потомък получава всички полета на всичките си предшественици и може да ги увеличи със свои собствени, но не може да ги замени или премахне. Следователно, колкото по-нисък е класът в йерархичното дърво, толкова повече данни получават неговите обекти на свое разположение.

Процедурите и функциите, капсулирани в клас, се наричат ​​методи. Те се декларират по същия начин като нормалните подпрограми:

тип TMyClass = клас

Достъпът до методите на класа, както и до неговите полета, е възможен чрез съставни имена:

Както вече споменахме, методите на класа могат да се припокриват в наследниците. Например: въведете TParentClass = клас

Потомците на двата класа могат да изпълнят DoWork процедура с подобно име, но като цяло ще го направят по различен начин. Такова заместване на метода се нарича статично, защото се изпълнява от компилатора.

Нека, например, родителският клас, използващ съответно методите Show и Hide, покаже нещо на екрана или скрие изображението. За създаванеизображения, той използва метода Draw с булев параметър:

Изпълнението на методите Show и Hide е много просто:

Методите Draw върху родителя и детето имат различни реализации и създават различни изображения. В резултат на това родителските методи Show и Hide ще скрият или покажат определени изображения в зависимост от конкретната реализация на метода Draw във всеки от техните наследници. Динамичното обвързване напълно прилага класовия полиморфизъм.

Ако даден метод се извиква често или ако се изисква да се минимизира времето за извикване към него, той трябва да бъде деклариран като виртуален (виртуален). Всички други методи са по-добре декларирани като динамични.

Динамично заменените методи често не могат да направят нищо. Такива методи се наричат ​​абстрактни, те трябва да се припокриват в потомците. Програмистът може да предотврати извикването на абстрактен метод, като го декларира с абстрактната директива. Например:

TVisualChildObject = class(TWinControl) Процедура Draw(IsShow: Boolean); отмяна; край; var aVisualObject: TVisualObject; aVisualChild: TVisualChildObject; започнете aVisualObject.Show; aVisualChild.Show;

Извикване на неотменен абстрактен метод причинява грешка по време на изпълнение. Разбира се, в една добре написана програма абстрактните методи никога не се извикват. Класовете, съдържащи абстрактни методи, се наричат ​​абстрактни. Такива класове капсулират общите свойства на своите неабстрактни потомци, но обектите на абстрактните класове никога не се създават или използват. За да се използват абстрактните класове, библиотеката с класове на Delphi включва класове наследници, които заместват абстрактните методи на родителя.

Всички полета на обект, както и методите на класа, които работят с неговите полета, могат да бъдат извикани само след като обектът е създаден чрез извикване на конструктора,тъй като конструкторите разпределят обект в динамична памет и правят указателя, съдържащ се в обекта, валиден.

var MyObject: TMyClass; започнете MyObject.IntField := 0; // Грешка! Не създавайте обект

// конструктор! MyObject := TMyClass.Create; // Направете следното: създайте обект MyObject.IntField := 0; // и достъп до неговото поле

MyObject.Free; // Унищожи ненужния обект

Специално за унищожаване на обекти в модула System е дефинирана процедурата FreeAndNil, която не само унищожава обекта, но и поставя стойността NIL в неговия указател (да напомня, че това е идентификаторът на обекта):

FreeAndNil(MyObject) Процедурата FreeAndNil беше въведена за първи път в Delphi версия 5.

Повечето конструктори изпълняват някои от действията, необходими за правилното функциониране на обекта. Следователно в конструктора на дъщерния клас първо трябва да извикате конструктора на неговия родител и едва след това да извършите допълнителни действия. Извикването на всеки метод на родителския клас се постига с помощта на запазената дума inherited (наследено):

Стойност: Цяло число); // Възможна реализация на конструктора begin inherited Create(AOwner); // Извикване на наследеното

// конструктор IntField := Стойност; // Внедряване на допълнителни

Отбелязвам, че когато извиквате родителския метод със същото име, можете да пропуснете името на метода и параметрите за извикването му.

Някои методи могат да бъдат извикани без създаване и инициализиране на обект. Такива методи се наричат ​​​​класови методи и се декларират с помощта на запазената дума class:

За разлика от други версии на Delphi, във версия 4 и по-късни стана възможно да има няколко метода с едно и също име в рамките на един клас. Описаният по-горе механизъм за замяна на родителски метод с дъщерен метод със същото имекара детето да "не вижда" отменения родителски метод и може да има достъп до него само с помощта на запазената наследена дума. Delphi 4 въвежда запазената дума overlpad (презареждане), която прави видими както родителските, така и дъщерните методи с едно и също име.

За да могат едноименните методи да се различават един от друг, всеки от тях трябва да има уникален набор от параметри. По време на изпълнение на програмата, при извикване на един от едноименните методи, програмата проверява вида и броя на действителните параметри на извикването и избира необходимия метод.

В следващия пример класът TForml използва до 4 метода Close със същото име. Само един от тях - наследен метод без параметър - изпълнява основните си функции - затваря прозореца. Три други се различават по набор от параметри и показват съобщение в заглавието на прозореца.

Поставете четири TButton на празен формуляр и напишете следните манипулатори за техните OnClick събития:

И накрая, в раздела за изпълнение, поставете декларациите на декларираните методи:

Сега, след стартиране на програмата, първите три бутона ще извикат методите Close на класа TForml и ще променят заглавието на прозореца, докато бутонът Button4 ще извика метода Close на родителския клас TForm и ще затвори прозореца.

тип TaClass = клас

В контекста на програма дадено свойство се държи като обикновено поле. Например, можем да напишем твърдения като това:

aClass.Destroy; // Премахване на ненужен обект

Разликата между това и следното изявление е, че при достъп до свойството автоматично се свързва методът SetField, в който могат да се изпълняват конкретни действия:

За разлика от променливата, свойство не може да бъде предадено на подпрограма по име, тоест като параметър var.

Аконяма нужда от специални действия при четене или писане на свойство, вместо името на съответния метод можете да посочите името на полето:

тип TaClass - клас

IntFiled: Цели числа-процедура SetField(Стойност: Цяло число); свойство IntegerValue:

Ако искате свойството да е само за четене или само за запис, трябва да пропуснете съответно частта за писане или четене. По принцип едно свойство може да не е свързано с поле. Всъщност той описва един или два метода, които извършват някакво действие върху данни от същия тип като свойството.

Събитията заемат някаква междинна позиция между свойствата и методите: от една страна, те, подобно на свойствата, могат да бъдат предоставени в прозореца на инспектора на обекти, от друга страна, те съдържат програмен код, който се изпълнява в отговор на променено състояние на програмата или съобщение на Windows.

Технически се декларират по същия начин като свойствата, със запазената дума свойство. Типът на това „имот“ обаче трябва да е един от предварително декларираните процедурни типове.

тип TEvent = процедура; MyClass = клас (TComponent) защитен FEvent: TEvent; публичен

Вече можем да поставим събитието в публикуваната секция:

MyClass = клас (TComponent) защитен FEvent: TEvent; публикувани

Ако пропуснем думите на обект от декларацията за процедурен тип, компилаторът няма да генерира информация за типа по време на изпълнение и можем да поставим декларацията за събитие във всеки раздел, различен от публикувания. Това означава, че няма да можем да работим със събитието с помощта на Object Inspector.