Moduły Delphi 6 - wszystko co powinieneś o nich wiedzieć

michalkopacz
<font 'verdana'="'verdana'">Spis treści 1. Wstęp 2. Typy modułów 2.1 Moduł główny projektu 2.2 Moduł formularza 2.3 Zwykły moduł 3.Budowa modułu 3.1 Budowa i składnia programu (moduł główny projektu) 3.2 Budowa i składnia modułu (zwykły moduł, moduł formularza) 3.2.1 Słowo kluczowe unit 3.2.2 Sekcja interface 3.2.3 Sekcja implementation 3.2.4 Sekcja initialization 3.2.5 Sekcja finalization 4. Zależności między modułami - sekcja uses 4.1 Struktura sekcji uses 4.2 Bezpośrednia i pośrednia zależność między modułami 4.3 Cykliczna zależność między modułami 5. Warsztat 5.1 Quiz 5.2 Ćwiczenia 5.3 Dodatki A. Odpowiedzi do Quizu B. Rozszerzenia plików stosowane w Delphi </span>

1. Wstęp Object Pascal zaliczany jest do tzw. modularnych języków programowania. Oznacza to, że podstawowym elementem każdego programu jest moduł. Modularna struktura programu pozwala na odpowiednie grupowanie określonych, powiązanych ze sobą części kodu. Kod ten zapisywany jest w pliku tekstowym, czyli module i kompilowany na kod wykonywalny, zrozumiały dla komputera. Każdy moduł jest kompilowany i zapisywany oddzielnie. Aby stworzyć aplikację, skompilowane moduły muszą być połączone. Proces łączenia modułów nazywamy linkowaniem. Moduł (ang. unit) to plik tekstowy, który może być kompilowany do postaci kodu wykonywalnego tzn. kod źródłowy tłumaczony jest na język zrozumiały dla komputera. 2. Typy modułów W Delphi mamy do dyspozycji trzy rodzaje modułów: * Moduł główny projektu (ang. project source unit), * Moduł formularza, * ?Zwykły? moduł (moduł niezwiązany z formularzem). Aplikacja Delphi z graficznym interfejsem (aplikacja GUI) posiada, co najmniej dwa moduły, moduł główny projektu i moduł formularza głównego. Aplikacja GUI (Graphical User Interface) to 32-bitowy program posiadający formularz główny (może posiadać również dodatkowe formularze), na którym znajdują się elementy graficzne takie jak: okna, menu, pola edycyjne, przyciski i wiele innych komponentów, dzięki którym aplikacja staje się łatwiejsza w użyciu. Oprócz aplikacji GUI wyróżniamy również aplikacje terminalowe (konsolowe), uruchamiające się w oknie ?Tryb MS-DOS?. 2.1 Moduł główny projektu W odróżnieniu od większości tradycyjnych aplikacji tworzonych w Turbo Pascalu, gdzie cały kod źródłowy zawierał się w ?programie głównym?, prawie cały kod aplikacji napisanych w Delphi zawarty jest w modułach, natomiast ?program główny? zredukowany został do roli organizacyjnej. Moduł główny projektu (ang. project source unit) zawiera tekst źródłowy projektu i posiada rozszerzenie .DPR (od Delphi PRoject). Możesz obejrzeć jego zawartość, wybierając z menu opcję Project|View Source. 2.2 Moduł formularza Drugi typ modułu, który zawsze występuje w aplikacji GUI, to moduł formularza głównego. Moduł formularza, jak sama nazwa wskazuje, zawiera kod źródłowy związany z formularzem. Każdemu formularzowi odpowiada jeden moduł, lecz nie zawsze jest odwrotnie, ponieważ mogą istnieć moduły niereprezentujące formularzy. Pliki modułu formularza mają rozszerzenie .PAS. 2.3 ?Zwykły? moduł Istnieje także trzeci typ modułów, które możemy stosować w aplikacjach Delphi. Zawierają one tylko kod źródłowy, wywoływany z innych modułów w projekcie, i nie są związane z formularzami. 3. Budowa modułu Moduły w Delphi muszą mieć pewien określony format (określoną budowę). Jest to niezbędne, aby kompilator mógł skompilować kod do postaci wykonywalnej. 3.1 Budowa i składnia programu (moduł główny projektu) Moduł główny projektu zawiera na początku słowo kluczowe program, po którym występuje nazwa modułu, sekcję uses (opcjonalnie) i blok kodu objęty słowami kluczowymi begin i end. Oto przykładowa postać programu głównego Delphi: Wydruk 1. Kod źródłowy domyślnego projektu Delphi ```delphi 1: program Project1; 2: 3: uses 4: Forms, 5: Unit1 in 'Unit1.pas' {Form1}; 6: 7: {$R *.res} 8: 9: begin 10: Application.Initialize; 11: Application.CreateForm(TForm1, Form1); 12: Application.Run; 13: end. ``` Uwaga! Numery linii przedstawione na powyższym wydruku (również na niektórych wydrukach w dalszej części artykułu) nie są częścią kodu; umieściłem je tam po to, aby móc się do nich odwoływać w tekście. W Pascalu nie numeruje się linii kodu źródłowego, w przeciwieństwie do niektórych innych języków programowania (np. starszych wersji Basica). Linia 1. zawiera słowo program, które wskazuje, iż jest to moduł główny projektu. Bezpośrednio za nim znajduje się nazwa projektu zakończona średnikiem. Nazwa projektu musi być identyczna jak nazwa pliku projektu. W powyższym przykładzie po słowie program występuje nazwa Project1, tak więc plik projektu powinien nazywać się Project1.dpr. W standardowym Pascalu słowo kluczowe program mogło zawierać dodatkowe parametry, które występowały po nazwie programu. Kompilator Object Pascala ignoruje te parametry. Na przykład: ```delphi program Calc(input, output); ``` W linii 3. zaczyna się sekcja uses. Zawiera ona nazwy wszystkich modułów, do których odwołuje się ten moduł. Na przykład w linii 11.: ```delphi Application.CreateForm(TForm1, Form1); ``` jest odwołanie do informacji, której nie ma w module głównym. Procedura Application.CreateForm umieszczona jest w module Forms.pas, natomiast TForm1 i Form1 znajdują się w module głównego formularza Unit1.pas. Sekcja uses informuje Delphi, gdzie ma szukać informacji potrzebnej do skompilowania danego modułu. ```delphi uses Forms, Unit1 in 'Unit1.pas' {Form1}; ``` Zwróć uwagę, że lista ta zawiera nazwy dwóch modułów: Forms i Unit1. Druga linia w tej sekcji jest trochę niestandardowa. Występuje ona tylko w pliku źródłowym modułu głównego i oznacza odwołanie do formularza zawartego w pliku Unit1.pas. W linii 7. występuje dyrektywa kompilatora, która nakazuje mu dołączenie pliku zasobów projektu (ang. resources) do programu. Linie od 9. do 13. zawierają blok kodu, który jest ograniczony słowami kluczowymi begin i end. Zauważ, że końcowy end modułu kończy się kropką. W module może występować nieskończenie wiele bloków kodów zawartych pomiędzy begin i end, jednak end z kropką występuje jedynie na końcu modułu. Instrukcje zawarte w liniach od 10. do 12. odpowiedzialne są za inicjalizację programu, utworzenie jego głównego formularza i jego uruchomienie. 3.2 Budowa i składnia modułu (?zwykły? moduł, moduł formularza)) W module zawarte są typy danych (włączając klasy), stałe, zmienne oraz procedury i funkcje. Każdy moduł zapisywany jest w oddzielnym pliku modułu (.PAS). Plik modułu formularza zaczyna się słowem kluczowym unit (linia 1.), po którym występują sekcje interface (linia 3.), implementation (linia 20.), initialization (linia 24.) i finalization (linia 26.). Sekcje initialization i finalization są opcjonalne (Nowo utworzony moduł formularza nie zawiera sekcji initialization i finalization. Dopisałem je na potrzeby artykułu). Szkielet pliku modułu formularza przedstawia wydruk 2. Wydruk 2. Szkielet kodu modułu formularza ```delphi 1: unit Unit1; 2: 3: interface 4: 5: uses 6: Windows, Messages, SysUtils, Variants, Classes, Graphics, 7: Controls, Forms, Dialogs; 8: 9: type 10: TForm1 = class(TForm) 11: private 12: { Private declarations } 13: public 14: { Public declarations } 15: end; 16: 17: var 18: Form1: TForm1; 19: 20: implementation 21: 22: {$R *.dfm} 23: 24: initialization 25: 26: finalization 27: 28: end. ``` Jak wcześniej wspomniałem każdemu formularzowi odpowiada jeden moduł. Poniższy wydruk przedstawia deklarację formularza jako typu: Wydruk 3. Deklarację formularza jako typu ```delphi type TForm1 = class(TForm) private { Private declarations } public { Public declarations } end; ``` Jak łatwo zauważyć, formularz jest obiektem o typie pochodnym w stosunku do typu TForm. Stosowne komentarze wskazują miejsce do wpisania własnych deklaracji ? prywatnych i publicznych. Wybierając opcję File|New|Unit naszym oczom ukaże się inny typ modułu w Pascalu, nazwany przez zemnie ?zwykłym modułem?. Szkielet tego modułu przedstawia poniższy wydruk: Wydruk 4. Nowo utworzony moduł ```delphi 1: unit Unit2; 2: 3: interface 4: 5: implementation 6: 7: end. ``` ?Zwykły moduł? różni się od modułu formularza tym, iż jest bardziej ?zubożały?. Zawiera on tylko deklaracje sekcji interface i implementation, oraz nazwę modułu (może on również zawierać sekcje initialization i finalization). Każdy moduł musi być zakończony słowem kluczowym end z kropką. Bardziej szczegółowy opis poszczególnych składników modułu znajdziesz w poniższych podpunktach. 3.2.1 Słowo kluczowe unit Bezpośrednio po słowie kluczowym unit występuje nazwa modułu, która jest zakończona średnikiem. Nazwa pliku modułu musi być identyczna jak nazwa modułu. Na przykład w poniższej deklaracji: ```delphi unit MainForm; ``` po słowie unit występuje nazwa MainForm, tak więc plik modułu będzie nazywał się MainForm.pas, a plik skompilowanego modułu MainForm.dcu. Nazwy modułów należących do danego projektu nie mogą być identyczne. Oznacz to, że program nie może zawierać dwóch tak samo nazywających się plików modułu. 3.2.2 Sekcja interface W module sekcja interface zaczyna się słowem kluczowym interface i kończy się początkiem następnej sekcji, czyli sekcji implementation. W sekcji interface zadeklarowane są stałe, typy, zmienne, funkcje i procedury, które są dostępne dla klientów, czyli modułów, które odwołują się do danego modułu ( w sekcji uses tych modułów zadeklarowany jest dany moduł). Te deklaracje zwane są publicznymi (ang. public), ponieważ klient może używać ich tak, jakby były one zadeklarowane w kliencie. W sekcji interface zadeklarowane są tylko nazwy funkcji lub procedur. Właściwy kod procedur i funkcji znajduje się w sekcji implementation. Poniższy wydruk przedstawia taką deklarację: Wydruk 5. Deklaracja procedury Button1Click w sekcji interface ```delphi unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); {deklaracja procedury Button1Click w sekcji interface} private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin {kod procedury Button1Click} end; end. ``` Sekcja ta może zawierać również słowo kluczowe uses, jednak musi ono pojawić się natychmiast po słowie interface. 3.2.3 Sekcja implementation Sekcja implementation zaczyna się słowem kluczowym implementation i trwa, dopóki nie zacznie się sekcja initialization lub, jeśli nie istnieje sekcja initialization, dopóki nie wystąpi słowo end kończące moduł. Sekcja ta zawiera definicje (kod właściwy) funkcji i procedur zadeklarowanych w sekcji interface. Sekcja implementation może również zawierać definicje procedur i funkcji, które nie zostały zadeklarowane w sekcji interface, jednakże są to procedury i funkcje prywatne (ang. private), czyli nie dostępne dla klientów. Przykład wyżej opisanych deklaracji przedstawia wydruk 6. : Wydruk 6. Definicje procedur w sekcji implementation ```delphi unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure MojaProcedura; {deklaracja procedury MojaProcedura w sekcji interface} private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.MojaProcedura; //Procedura publiczna begin {definicja (kod) procedury MojaProcedura w sekcji implementation} end; procedure MojaProcedura2; //Procedura prywatna begin {definicja (kod) procedury MojaProcedura2 w sekcji implementation} end; end. ``` Oprócz definicji funkcji i procedur, sekcja implementation może zawierać również deklaracje stałych, zmiennych i typów danych. Są to deklaracje prywatne, tzn. niedostępne dla klientów. Sekcja implementation może zawierać słowo kluczowe uses (podobnie jak sekcja interface), które występuje po słowie implementation. Ważnym szczegółem w przedstawionym wydruku 6. jest dyrektywa: ```delphi {$R *.dfm} ``` Służy ona do połączenia modułu z reprezentującym formularz plikiem zasobu o rozszerzeniu .DFM (od Delphi ForM). Gwiazdka zastępująca nazwę pliku nie spełnia tutaj roli szablonu, lecz symbolizuje nazwę modułu. I tak, dla modułu unit1.pas napis *.dfm oznacza to samo, co unit1.dfm. 3.2.4 Sekcja initialization W sekcji initialization umieszcza się kod, który musi być wykonany w momencie ładowania modułu do pamięci. Sekcja ta jest opcjonalna, co oznacz, że nie musi występować w module. Rozpoczyna się od dyrektywy initialization, a kończy dyrektywą end, kończącą równocześnie cały moduł, bądź też słowem finalization. Kolejność wykonywania części inicjacyjnych (sekcji initialization) poszczególnych modułów zależy od ich wzajemnego uzależnienia wynikającego z dyrektyw uses. 3.2.5 Sekcja finalization W sekcji finalization umieszcza się kod wykonywany w chwili usuwania modułu z pamięci. Sekcja finalization, podobnie jak sekcja initialization, jest opcjonalna. Jeżeli jednak występuje w module, to nie wolno pominąć sekcji initialization. Rozpoczyna się od dyrektywy finalization a kończy dyrektywą end, kończącą zarazem cały moduł. Pojawiła się w Delphi 2, zastępując znany z Turbo Pascala mechanizm tzw. funkcji kończących ExitProc (mechanizm ten istniał jeszcze w Delphi 1, wspierany dodatkowo przez funkcję AddExitProc). Część kończąca (sekcja finalization) jest wykonywana przeciwnie do części inicjacyjnej. Na przykład, jeśli aplikacja inicjuje moduły w kolejności A, B i C (litery oznaczają nazwy modułów), to sfinalizuje (zakończy) je w kolejności C, B i A. Przykład kolejności inicjowania i finalizowania modułów przedstawia ćwiczenie 1. 4. Zależności między modułami - sekcja uses Zależności pomiędzy modułami wynikają z ich wzajemnej deklaracji w sekcji uses. Zanim jednak opiszę te zależności, przedstawię najpierw budowę sekcji uses. 4.1 Struktura sekcji uses Sekcja uses w module lub programie głównym zawiera listę modułów, do których występują odwołania. Dyrektywa uses może występować w: * w pliku projektu programu głównego lub biblioteki, * w sekcji interface modułu, * w sekcji implementation modułu. Najczęściej sekcja uses występuje w module głównym projektu lub części interface. Każdy moduł może zawierać, co najwyżej dwie sekcje uses. Sekcja uses zaczyna się słowem kluczowym uses, po którym występuje lista modułów, zakończona średnikiem. Nazwy modułów muszą być oddzielone od siebie przecinkami. Na przykład: ```delphi uses Forms, Main; ``` albo ```delphi uses Windows, Messages, SysUtils, Strings, Classes, Unit2, MyUnit; ``` Nie jest natomiast istotny podział na linie ? poniższe dwie sekcje są dla kompilatora równoważne: ```delphi uses SysUtils, Types, Classes, Graphics, Controls; ``` ```delphi uses SysUtils, Types, Classes, Graphics, Controls; ``` W sekcji uses programu (modułu głównego projektu) lub biblioteki może występować nazwa modułu ze słowem in, po którym występuje nazwa pliku modułu, z lub bez ścieżki dostępu, ograniczona pojedynczymi znakami cudzysłowia. Na przykład: ```delphi uses Windows, Messages, SysUtils, Strings in 'C:\Classes\Strings.pas', Classes; ``` Ścieżka dostępu do pliku modułu może być względna. Używamy jej wtedy, gdy plik modułu znajduje się w podkatalogu. Na przykład, na poniższym wydruku: ```delphi uses QForms, Main, Extra in '../extra/extra.pas'; ``` plik modułu extra.pas znajduje się w katalogu extra, który znajduje się w katalogu projektu. Dyrektywę in używamy tylko w ostateczności, na przykład wtedy, kiedy plik modułu, do którego odwołujemy się w sekcji uses, znajduje się w innym folderze niż pliki projektu (naszego programu), a ścieżka dostępu do tego modułu nie jest zawarta w ogólnej Bibliotece ścieżek dostępu (tłumaczyłem z ang. general Library search path). Sekcja uses pozostałych modułów (moduł formularza, ?zwykły? moduł) nie może zawierać dyrektywy in. Ścieżka dostępu do każdego modułu, do którego się odwołujemy w danym module, musi znajdować się w ogólnej Bibliotece ścieżek dostępu, lub wszystkie moduły, do których się odwołujemy, muszą znajdować się w tym samym katalogu, co dany moduł. Ponadto, nazwy modułów muszą byś identyczne jak nazwy plików modułu. Moduł używany automatycznie przez każdy program to moduł System. Nie jest on jednak deklarowany w sekcji uses w sposób jawny (nazwa tego modułu nie występuje w sekcji uses, jednak program odwołuje się do tego modułu). Inne standartowe moduły, takie jak SysUtils muszą być zadeklarowane w sekcji uses. W większości przypadków, wszystkie potrzebne moduły umieszczane są do sekcji uses podczas tworzenia projektu. 4.2 Bezpośrednia i pośrednia zależność między modułami Jeżeli moduł A odwołuje się do stałych, zmiennych, typów, procedur i funkcji, które są zawarte w module B, wtedy moduł B musi być zadeklarowany w module A w sposób jawny. Uogólniając, jeżeli nazwa modułu B występuje na liście uses modułu A, to mówimy, że moduł A jest bezpośrednio zależny (ang. direct unit references) od modułu B. Jeżeli w module B na liście uses występuje nazwa C, to moduł A jest zależny pośrednio (ang. indirect unit references) od modułu C ? poprzez moduł B. W takim wypadku nazwa modułu C nie musi zawierać się w sekcji uses modułu A, jednak kompilator musi być zdolny znaleźć moduły B i C, aby mógł skompilować moduł A. Ogólnie rzecz biorąc, opisana zależność pomiędzy modułami może prowadzić przez większą liczbę modułów pośrednich. Poniższy wydruk ilustruje opisane wyżej zależności. Wydruk 7. Bezpośrednia i pośrednia zależność między modułami ```delphi unit A; interface uses B; const a = b; implementation end. ----------------------------------------------------------------------- unit B; interface uses C; const b = c; implementation end. ----------------------------------------------------------------------- unit C; interface const c = 1; implementation end.
``` W powyższym przykładzie moduł A jest zależny bezpośrednio od modułu B, który jest zależny bezpośrednio od modułu C. Tak, więc moduł A jest pośrednio zależny od modułu C. Ponieważ moduł C nie jest zadeklarowany w sekcji uses modułu A, stąd wszystkie stałe, zmienne itp. występujące w module C, nie są dostępne dla modułu A. 4.3 Cykliczna zależność między modułami Opisana w punkcie 4.2 bezpośrednia zależność między modułami ma bardzo wyraźny aspekt praktyczny. Jeżeli moduł X zależny jest od modułu Y (poprzez deklarację modułu Y w sekcji uses części publicznej (sekcji interface) modułu X), to skompilowanie (przynajmniej) części publicznej modułu Y jest konieczne do tego, by mogła rozpocząć się kompilacja modułu X. Jeżeli więc zdarzy się tak, iż przynajmniej dwa moduły (nazwijmy je P i Q) będą od siebie nawzajem zależne, nie będzie możliwe skompilowanie ani modułu P, ani Q; w efekcie nie będzie możliwe skompilowanie projektu. Takie wzajemne uzależnienie publicznych części modułów nazywamy w Pascalu odwołaniem cyklicznym (ang. circular unit reference); powoduje ono oczywiście błąd kompilacji. Poniższe dwa moduły uwikłane są w odwołanie cykliczne: Wydruk 8. Cykliczna zależność między modułami ```delphi unit P; interface uses Q; implementation end. ----------------------------------------------------------------------- unit Q; interface uses P; implementation end. ``` Należy zaznaczyć, iż listy uses w części prywatnej modułów nie powodują opisanego uzależnienia. Wynika stąd prosty wniosek, iż pierwszym krokiem w celu pozbycia się odwołania cyklicznego powinna być próba przeniesienia kolidujących nazw na listach uses z części publicznej do części prywatnej modułów (chodzi oczywiście o te nazwy, które w części publicznej nie są potrzebne i znalazły się tam np. przez niedopatrzenie). Jeżeli nie rozwiąże to problemu, należy stworzyć odrębny moduł i przenieść do jego części publicznej te elementy, które stanowią przyczynę wystąpienia odwołania cyklicznego. Przykład pozbycia się cyklicznej zależności miedzy modułami przedstawia poniższy wydruk: Wydruk 9. Przykład pozbycia się odwołania cyklicznego ```delphi unit P; interface uses Q; implementation end. ----------------------------------------------------------------------- unit Q; interface implementation uses P; end. ``` 5. Warsztat Warsztat składa się z pytań kontrolnych oraz ćwiczeń utrwalających i pogłębiających zdobytą wiedzę. W razie trudności lub wątpliwości, odpowiedzi na pytania Quizu zamieszczone są w dodatku A. 5.1 Quiz Quiz składa się z dziesięciu pytań zamkniętych. Spośród odpowiedzi A, B i C tylko jedna jest prawidłowa. 1. Jakie jest rozszerzenie pliku zawierającego moduł Object Pascala? A) .dcu B) .pas C) .dpr 2. Ile modułów głównych projektu może zawierać pojedynczy program? A) tylko jeden B) nieskończenie wiele C) to zależy od rodzaju tworzonego programu 3. Który rodzaj modułu nie posiada sekcji interface? A) moduł główny projektu B) moduł formularza C) ?zwykły? moduł 4. Sekcja implementation nazywana jest również: A) częścią publiczną modułu B) częścią chronioną modułu C) częścią prywatną modułu 5. Sekcja uses zawiera nazwy modułów, do których występują odwołania. Każdy moduł może zawierać co najwyżej: A) jedną sekcje uses B) dwie sekcje uses C) trzy sekcje uses 6. Która z poniższych zależności miedzy modułami jest przyczyną niemożliwości kompilacji programu? A) pośrednia zależność między modułami B) bezpośrednia zależność między modułami C) cykliczna zależność między modułami 7. Proces łączenia modułów nazywamy: A) kompilacją B) linkowaniem C) replikacją 8. Sekcja uses nie może występować w: A) sekcji interface modułu B) sekcji initialization modułu C) w module głównym biblioteki 9. W sekcji implementation mogą wstępować: A) definicje (kod właściwy) funkcji i procedur B) deklaracje nagłówków funkcji i procedur C) definicje i deklaracje funkcji i procedur 10. Aplikacja konsolowa to : A) aplikacja z graficznym interfejsem, zwana również aplikacją GUI B) 16-bitowy program działający zarówno w systemie operacyjnym Windows, jak również w systemie Linux C) aplikacja terminalowa, działająca w systemie MS-DOS 5.2 Ćwiczenia Najlepszą metodą pogłębienia i opanowania zdobytej wiedzy jest praktyka. Poniżej zamieszczam 2 ćwiczenia, które, mam nadzieję, utrwalą zdobyte wiadomości na temat struktury modułów. Ćwiczenie 1 Zagadnienie: Sekcje initialization i finalization Pierwsze ćwiczenie ma na celu opanowanie kolejności inicjowania i finalizowania poszczególnych modułów. A więc do dzieła: 1.Poleceniem menu File|New|Other|Console Aplication stwórz nowy projekt programu, który będziemy testować w okienku tekstowym. 2.Dodaj do projektu dwa moduły. W tym celu dwukrotnie wykonaj polecenie File|New|Unit. 3.Poleceniem menu File|Save All zapisz projekt na dysku. Nazwę modułu projektu pozostaw bez zmian. Dodane moduły nazwij kolejno UnitA.pas oraz UnitB.pas. 4.Nie pozostaje nam nic innego, jak poszczególne zakładki wypełnić kodem przedstawionym na poniższych wydrukach. ```delphi program Project1; {$APPTYPE CONSOLE} uses UnitA; begin WriteLN('Program glowny'); Write('Nacisnij klawisz ... '); ReadLN; end. unit UnitA; interface uses UnitB; implementation initialization WriteLN('Inicjacja modulu A'); finalization WriteLN('Finalizacja modulu A'); Write('Nacisnij klawisz ... '); ReadLN; end. unit UnitB; interface implementation initialization WriteLN('Inicjacja modulu B'); finalization WriteLN('Finalizacja modulu B'); Write('Nacisnij klawisz ... '); ReadLN; end. ``` 6. Zapisz ponownie projekt (File|Save All). 7.Skompiluj i uruchom program poleceniem menu Project|Run. Analizując zapisy przedstawione na wydrukach oraz porównując je z wynikiem działania aplikacji, bez problemu zauważymy, w jakiej kolejności inicjowane i finalizowane są w programie poszczególne moduły. Ćwiczenie 2 Zagadnienie: Odwołania cykliczne W tym ćwiczeniu zademonstruję program uwikłany w odwołanie cykliczne. Pokażę również, jak pozbyć się cyklicznej zależności między modułami. 1.Poleceniem menu File|New|Other|Console Aplication stwórz nową aplikację konsolową. 2.Dodaj do projektu dwa moduł (File|New|Unit). 3.Poleceniem menu File|Save All zapisz projekt na dysku. Nazwy modułów oraz programu pozostaw domyślne. 4.Wypełnij moduły kodem przedstawionym na poniższych wydrukach. ```delphi program Project1; {$APPTYPE CONSOLE} uses Unit1; begin WriteLN('Jesli ten program sie uruchomil, to znaczy,'); WriteLN('ze pozbyles sie odwolania cyklicznego.'); Write('Nacisnij klawisz ... '); ReadLN; end. unit Unit1; interface uses Unit2; implementation end. unit Unit2; interface uses Unit1; implementation end. ``` 5.Zapisz ponownie projekt (File|Save All). 6.Skompiluj i uruchom program poleceniem menu Project|Run. I tu spotyka Cię niespodzianka. Program nie uruchomi się, ponieważ kompilator sygnalizuje błąd: [Fatal Error] Unit2.pas(4): Circular unit reference to 'Unit2' Powyższy błąd oznacza, że między modułem Unit1, a modułem Unit2 zachodzi odwołanie cykliczne. Aby zlikwidować błąd i tym samym pozbyć się odwołania cyklicznego, wykonaj poniższe czynności: 7.Przenieś sekcję uses z sekcji interface do sekcji implementation w module Unit2. Po wykonaniu tej czynności kod w module Unit2 powinien wyglądać tak, jak na poniższym wydruku. ```delphi unit Unit2; interface implementation uses Unit1; end. ``` 8.Uruchom teraz program. Jeśli wyświetli się okienko tekstowe to znaczy, że pozbyłeś się odwołania cyklicznego. Zademonstrowałem tu tylko jeden sposób pozbycia się odwołania cyklicznego. Można było również pozbyć się deklaracji modułu Unit1 w sekcji uses modułu Unit2. 5.3 Dodatki A. Odpowiedzi do Quizu Pyt. Odp. 1 B 2 A 3 A 4 C 5 A 6 C 7 B 8 B 9 A 10 C B. Rozszerzenia plików stosowane w Delphi Element Rozszerzenie Pełna nazwa Plik projektu .DPR Delphi Project Plik grupy projektowej .BPG Borland Project Group Plik kodu źródłowego .PAS Pascal Plik formularza .DFM Delphi Form Module Skompilowany plik modułu .DCU Delphi Compiled Module Skompilowany plik zasobów .RES / .DCR Resource / Delphi Compiled Resource Zapisane ustawienia pulpitu .DSK Desktop Ustawienia projektu .DOF Delphi Options File Pliki źródłowe pakietu .DPK Delphi Package Skompilowany pakiet .BPL Borland Package Libraries Układ pulpitu .DST Desktop Settings Plik opcji kompilatora aplikacji konsolowej .CFG Configuration Dołączony kod źródłowy .INC Include Autor: Michał Kopacz E-mail: [email protected]

7 komentarzy

Nazwa modułu A w module B, w sekcji:

  • interface: moduł A widoczny na zewnątrz modułu B
  • implementation: moduł A niewidoczny na zewnątrz modułu B

O widoczności mówimy wtedy, gdy moduł A jest włączony do innego modułu np.: C.

A co to za różnica, czy się napisze uses [nazwa modułu] w interface, czy się napisze to w implementation

2.1 Moduł główny projektu
2.2 Moduł formularza
2.3 ?Zwykły? moduł

Skąd to wziąłeś :D
Moduł (.PAS) to jedno, a program (.DPR) to co innego...

Artykul pierwsza klasa

edytowalem ci artykul i dodalem linki=kotwice, zeby bylo latwiej sie poruszac po artykule...
Sugestia - edytuj go i dopisz linki w calym spisie tresci.

Jezeli jestes autorem tego tesktu to ocena 6

Napiszcie co myslicie o tym artykule.
Zobaczcie również artykuły:
"Zamykanie systemu w Delphi".
"Funkcje generatora liczb pseudolosowych"
Autor.

Dobry artykul, wszystko dokladnie opisane.