Капсуловане и форми, използване на списъци от обекти и данни

  • Има и други ключови думи, свързани с обработката на изключения и най-често използваната е „at”. Тя може да е в комбинация с RAISE. Напр за да се покаже на коя машинна инструкция да се предаде възникналото изключение, се използва raise обект at адрес.

    Raise OutOfMemmory At ReturnAddr

    В програмните фрагменти може да има различни обработчици на изключения в един и същ блок try. Може да има произволен брой обработчици, които се изпълняват последователно. Поради тази причина по-общите от тях трябва да се поставят в края на блока. Използвайки йерархията на изключенията даден обработчик може да се извиква и за всички изключения наследници на обработеното от него изключение. Трябва да се има в предвид, че използването на един обработчик за вс изключения не е добра идея, по-добре да се оставят неизвестните изключения за обработка от Delphi, подразбиращият се в VCL обработчик показва на екрана съобщението за грешка, съдържащо се в изключението и след това възстановява нормалната работа на програмата. Този подразбиращ се обработчик може да се замени с обработчика ApplicationOnExeption.  Delphi дефинира и йерархия на изключенията, като може да се обработва всяко отделно изключение по специфичен начин или на веднъж цяла група от изключения. Когато програмата генерира изключение и текущата процедура не може да го обработи, програмата започва да търси, дали следващата процедура от стека (извикващата) има обработчик на изключения. Това означава, че програмата излиза от  текущата процедура и не изпълнява останалата част от кода. Блока finally се използва, за да се извършат някои действия (обикновено заключителни операции), операторите в този блок се изпълняват, дори и да не е възникнало изключение.

    Пр. Метод, който извършва някакви операции, изискващи много време и през това време показва пясъчен часовник. Тъй като в програмата има логическа грешка (променливата i достига стойност 0 и след това се дели на нея), тя ще бъде прекъсната и няма да може да възстанови подразбиращият се курсор. За това е нужен блока try-finally. При това блока try може да се следва или от блок except, или от блок finally, но не  от двата едновременно. Типичното решение в случая е да се използват 2 вложени блока try, единият с блок finally, а другият с блок except.

    Procedure  TForm1.BtnTryTryClick(Sender: TObject);

    Var i, j: integer;

    Begin

    screenCursor := crHourglass;

    j := 0;

    try

                  try

                                //дълго и грешно изчисление

                                For i:=1000 down 0 do

                                Begin

                                              J:=j+j DIV i ;

                                              messageDlg(‘total’+IntToStr(j), mtInformation, [mbOK],0);

                  finally

                                screenCursor := crDefault;

    except

                  on EDIVbyZero do

                  begin

                  //препредаване на изключението с ново състояние 

    Raise Exception.create(‘error in alg’);

    End; end; end;

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

    Капсуловане  и форми

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

    Var Form1: TForm1;

                  nClicks: integer;

    При това възникват 2 проблема. 1- данните не са свързани с конкретна инстанция на формата, а с цялата програма, ако всяка форма от този тип, трябва да има свое собствено копие на променливата, единственото решение е да се добави към класа на формата.

    Type TForm1 = class(TForm)

    Public nClick: integer;

    End;

    Втория проблем е, че ако променливата се дефинира като глобална или като public поле на формата, тя може да се променя без това да се отрази на кода и. Напр. Ако стойността на променливата е необходима само за четене от останалите форми, тя може да се декларира, като private и да се предостави метод за получаване на нейната текуща стойност.

    Type TForm1=class(TForm)

    Public

                  Function getClicks: integer;

    Private

                  nClicks: integer;

    end;

    function TForm1.getClicks : integer;

    begin

                  result := nClicks;

    end;

    Използване на списъци от обекти и данни

    За да се създаде списък от някакъв тип може да се декларира обект от тип TList да се въведат данни в него и след това да има достъп до тях с подходящо преобразуване на типовете. Напр. Декларират се 2 private променливи, представляващи съответно два списъка. 1-ят с числа, а 2-тя с дати.

    Tlist

    Private ListName, ListDate :TList //тези обекти се създават по време на създаване на форма