Tworzenie i wykorzystanie funkcji i procedur w języku Visual Basic
Transkrypt
Tworzenie i wykorzystanie funkcji i procedur w języku Visual Basic
Ten odcinek Akademii PC Kuriera poświęcony zostanie tworzeniu i wykorzystaniu funkcji i procedur w języku Visual Basic .NET. Czym są procedury? Efektywne tworzenie często polegać będzie na ponownym wykorzystywaniu wcześniej utworzonego kodu. Stworzone we wcześniejszych projektach rozwiązania w postaci procedur i funkcji można w szybki sposób zaadoptować do bieżących projektów. Procedury i funkcje będą również bardzo przydatne do implementacji często powtarzających się w aplikacji zadań czy obliczeń. Każda z funkcji i procedur określona jest przez jednoznaczną, unikalną w kodzie nazwę, pozwalającej na jej uruchomienie (wywołania) z poziomu kodu innej procedury. Po wywołaniu procedury jej kod realizowany jest linia po linii aż do napotkania jednego z wyrażenia kończącego procedurę lub nakazującego wyjście z procedury. Po wykonaniu procedury kontrola programu zwracana jest do procedury wywołującej. Typy procedur w Visual Basic .NET Procedury w Visual Basic .NET można podzielić na trzy kategorie: • Procedury Sub (procedury) • Procedury Function (funkcje) • Procedury Property (procedury obsługujące własności) Na potrzeby artykułu ograniczymy się tylko do dwóch pierwszych kategorii. Procedury Sub wykonują określone przez kod działania, ale nie mogą zwracać wartości do procedur wywołujących. Procedury obsługujące zdarzenie to również procedury Sub – obsługa zdarzenia polega przecież na wywołaniu odpowiedniej procedury. W odróżnieniu od Procedur Sub procedury Function mogą natomiast zwracać wartość do procedury wywołującej. Dostępność procedur Możliwość wywołania danej procedury uzależniona jest od użytego w czasie deklaracji modyfikatora dostępu. Możliwe modyfikatory dostępu dla procedur i funkcji to: • Public • Friend • Private • Protected Modyfikator Public zezwala na wywołanie danej procedury lub funkcji przez dowolny kod. Użycie modyfikatora Friend spowoduje, że dana procedura będzie mogła być wywoływana przez kod aplikacji i jakikolwiek kod znajdujący się w tym samym assembly (zespół modułów, danych i informacji o programie). Procedura lub funkcja zadeklarowana jako Private będzie procedurą prywatną dla danej jednostki kodu. Oznacza to, że będzie ją można wywołać tylko z modułu lub formularza zawierającego jej deklarację. Modyfikator Protected dotyczy programowania obiektowego w VB i pozwala na ograniczenie dostępu do procedur - metod danej klasy tylko dla dziedziczonych klas potomnych. Procedury Deklaracja procedury Sub ma następującą budowę: [Modyfikator dostępu] Sub NazwaProcedury (argumenty) End Sub Gdzie: • Modyfikator dostępu jest jednym ze słów kluczowych: Private, Friend, Public, Protect • NazwaProcedury – jest poprawnie określoną nazwą (nie rozpoczyna się od cyfry, nie zawiera znaku spacji, spełnia zasady analogiczne do nazw zmiennych) Argumenty Dowolna funkcja lub procedura często będzie wymagała danych, w oparciu o które będzie ona realizowała określone działania. Dane te nazywane są argumentami wejściowymi. Każde wywołanie funkcji lub procedury, która zawiera w swojej deklaracji argumenty wymagało będzie dostarczenia odpowiedniej liczby wartości. Argumenty mogą być przekazywane do procedur dwojako: poprzez wartość (ByVal) lub poprzez referencję (ByRef). Sposób przekazania argumentów określona jest w deklaracji procedury lub funkcji. Jeśli sposób przekazywania argumentów nie jest jawnie okreśłony, to domyślnie argumenty przekazywane są poprzez wartość. Lista argumentów składa się więc z ciągu następujących wyrażeń rozdzielonych przecinkami: [ByRef lub ByVal] NazwaArgumentu As TypDanych Jeśli argument przekazywany jest poprzez wartość (ByVal), to do wnętrza procedury przekazywana jest kopia danych przekazanych jako argumenty wejściowe. Oznacza to, że jeśli kod wnętrza procedury zmieni tę wartość, to zmiana ta dotyczyć będzie kopii wartości oryginalnej – nie będzie więc widoczna dla pozostałego kodu. Jeśli argument przekazywany jest poprzez referencję, to do wnętrza procedury przekazywany jest wskaźnik do miejsca w pamięci, gdzie przechowywana jest wartość. Jeśli kod wewnątrz procedury dokona zmiany wartości argumentu, to zmiana ta będzie widoczna dla kodu procedury wywołującej. Zwróćmy jeszcze uwagę na prosty fakt, iż przekazywanie do procedury jakichkolwiek danych, które nie są zmiennymi lub wartościami poprzez referencję często prowadzi do błędów logicznych w aplikacji. Przykładowo, jeśli do procedury przekażemy przez referencję stałą, to pomimo wykonania operacji na takim argumencie jej wartość nie ulegnie zmianie. Nie każdy z argumentów musi być obowiązkowy. Jeśli dany parametr jest opcjonalny, to jego deklaracja na liście argumentów wejściowych powinna rozpoczynać się od słowa kluczowego Optional. Następnie należy zadeklarować argument i określić jego stałą wartość domyślną. Wartość ta zostanie użyta, jeśli przy wywołaniu danej funkcji lub procedury wartość dla danego argumentu nie zostanie określona. Należy zwrócić również uwagę na fakt, że kolejność argumentów obowiązkowych i opcjonalnych nie może być dowolna w deklaracji. Każdy za wyjątkiem pierwszego argument opcjonalny musi być poprzedzony innym argumentem opcjonalnym, po ostatnim argumencie opcjonalnym nie może wystąpić argument obowiązkowy. Przykład: Poniższy przykład demonstruje sposób deklaracji procedury, która wyświetla komunikat informujący o sumie dwóch lub trzech liczb przekazanych jako argumenty wejściowe. Public Sub Dodaj(ByVal arg1 As Integer, ByVal arg2 As Integer, Optional ByVal arg3 As Integer = 0) MessageBox.Show(CStr(arg1 + arg2 + arg3)) End Sub Uwaga: linie 1 i 2 w powyższym kodzie powinny zostać zapisane w jednym wierszu Funkcje Deklaracja funkcji różni się od deklaracji procedury sub zamianą słów sub na function oraz określeniem typu danych dla wartości zwracanej przez funkcję. Nie należy również zapomnieć różnicy pomiędzy procedurą a funkcją – możliwości zwrócenia wartości obliczonej przez funkcję. Podobnie jak w wersji Visual Basic 6.0 można tego dokonać za pomocą przypisania wartości do nazwy funkcji. Należy jednak pamiętać, że funkcja będzie kontynuowała dalej swoje działanie, aż do pierwszego napotkania w swym kodzie końca funkcji (End Function) lub polecenia jej opuszczenia (Exit Function). Nowością w stosunku do wersji Visual Basic 6.0 jest możliwość użycia instrukcji Return. Instrukcja ta pozwala w szybki sposób zarówno zwrócić wartość jak i zakończyć działanie funkcji. Przedstawione powyżej wiadomości dotyczące funkcji prezentuje poniższy kod: Przykład: Function Suma(ByVal arg1 As Integer, ByVal arg2 As Integer) As Integer Return arg1 + arg2 End Function Wywoływanie funkcji i procedur Przedstawione informacje pozwalają już na napisanie własnej prostej procedury i funkcji. Aby wywołać utworzoną procedurę lub funkcję należy odwołać się do jej nazwy oraz określić wszystkie wymagane argumenty wejściowe. Należy pamiętać, że wartości argumentów wejściowych powinny albo odpowiadać zadeklarowanym typom danych albo umożliwiać dokonanie konwersji niejawnej. Poniższy kod demonstruje wywołanie uprzednio utworzonej procedury Dodaj oraz funkcji Suma w obsłudze zdarzenia Load formularza Form1. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dodaj(1, 2) MessageBox.Show(Suma(3, 4)) End Sub Uwaga: wiersze 1 i 2 w powyższym kodzie powinny zostać zapisany w jednej linii kodu. Wnikliwy czytelnik dostrzegł zapewne, że funkcja lub procedura może posiadać kilka argumentów opcjonalnych. Jak w takim razie wywołać funkcję lub procedurę określając tylko niektóre z nich? Spójrzmy na deklarację przykładowej funkcji z trzema argumentami opcjonalnymi: Public Sub ArgumentyOpcjonalne(Optional ByVal arg1 As Integer = 0, Optional ByVal arg2 As Integer = 0, Optional ByVal arg3 As Integer = 0) MessageBox.Show(arg1 + arg2 + arg3) End Sub Uwaga: wiersze 1 i 2 w powyższym kodzie powinny zostać zapisany w jednej linii kodu. Poniższy kod prezentuje przykładowe wywołania funkcji ArgumentyOpcjonalne: • Pomijamy wszystkie argumenty za wyjątkiem pierwszego ArgumentyOpcjonalne(1) • Przekazujemy tylko drugi z argumentów opcjonalnych ArgumentyOpcjonalne(, 2, ) • Przekazujemy tylko ostatni z argumentów opcjonalnych ArgumentyOpcjonalne(, , 3) • Przekazujemy tylko pierwszy i ostatni z argumentów opcjonalnych ArgumentyOpcjonalne(1, , 3) • Przekazujemy wszystkie argumenty opcjonalne ArgumentyOpcjonalne(1, 2, 3) Tablice argumentów Implementacja funkcji i procedur wymagających różnej ilości argumentów wejściowych nie zawsze jest możliwa. Przykładem funkcji, którą trudno byłoby zaimplementować korzystając tylko z argumentów obowiązkowych i opcjonalnych jest np. sumowanie od dwóch do stu liczb przekazanych jako argumenty. Deklarowanie takiej funkcji byłoby bardzo uciążliwe. Kolejnym utrudnieniem byłaby zmiana specyfikacji i uwarunkowań – np. zwiększenie wymagań określających ilość sumowanych liczb powyżej stu. Często spotykanym problemem, którego nie da się rozwiązać przy pomocy argumentów opcjonalnych jest również nieznajomość liczby argumentów wejściowych w czasie implementacji funkcji. Rozwiązaniem powyższych problemów może być tablica parametrów wejściowych. Przypomnijmy może, że tablica jest to struktura danych pozwalająca odwoływać się do grupy wartości tego samego typu poprzez nazwę oraz indeks elementu tablicy. Aby zadeklarować funkcję, której jednym z argumentów jest tablica parametrów należy nazwę określonego argumentu poprzedzić słowem kluczowym ParamArray. Przekazywana do funkcji tablica nie posiada narzuconych przez deklarację ograniczeń na wielkość i ilość wymiarów. Sposób korzystania z tablicy parametrów prezentuje poniższy przykład: Public Function Srednia(ByVal ParamArray Oceny() As Integer) As Double Dim i As Integer Dim suma As Integer Dim liczbaElementow As Integer liczbaElementow = UBound(Oceny) For i = 0 To liczbaElementow suma = suma + Oceny(i) Next Return suma / (liczbaElementow + 1) End Function Powyższa oblicza średnią arytmetyczną dowolnej liczby ocen. Funkcja na początku swego działania korzystając z funkcji Ubound zwracającej maksymalny indeks przekazanej tablicy. Ilość ta przechowywana jest w zmiennej liczbaElementow. Następnie korzystając z pętli For (tematyka sterowania programem, instrukcji warunkowych i pętli zostanie omówiona w kolejnym odcinku Akademii) oblicza sumę wszystkich elementów tablicy. Na końcu swego działania funkcja zwraca wartość liczbową – średnią – obliczoną jako iloraz sumy i liczby elementów. Ponieważ w Visual Basic .NET pierwszy z elementów tablicy ma indeks równy 0, dla poprawności obliczeń liczbę elementów zwiększamy dodatkowo o 1. Argument ParamArray jest domyślnie opcjonalny - jego pominięcie w czasie wywołania spowoduje, że do funkcji zostanie przekazana pusta tablica (tablica zawierająca zero elementów). Jako argumentu wejściowego można użyć tablicy lub wartości rozdzielonych znakiem przecinka. Demonstrują to następujące przykłady: • Przekazanie argumentu jako tablicy Dim TabWejsciowa() As Integer = {1, 3, 5, 7} ' to jest pięcioelementowa tablica Srednia(TabWejsciowa) ' przekazuję tablicę TabWejsciowa do funkcji • Przekazanie argumentów jako ciągu wartości Srednia(1, 3, 5, 7) Stosowanie tablicy parametrów wymaga jednak przestrzegania następujących reguł: • Można zadeklarować tylko jeden taki argument • Argument w postaci tablicy argumentów musi być ostatnim argumentem i jedynym argumentem opcjonalnym w deklaracji • Tablica musi być przekazana przez wartość (ByVal) • Przekazana tablica jest jednowymiarowa • Wszystkie dane, jakie zawiera tablica muszą być zgodne co do typu z deklaracją Argumenty przekazywane do funkcji mogą być również tablicami. Następująca funkcja zwraca iloraz wyznaczników dwóch macierzy o wymiarach 2x2: Public Function IlorazWyznacznikow(ByVal Macierz1(,) As Integer, ByVal Macierz2(,) As Integer) Dim Wyznacznik1 As Double Dim Wyznacznik2 As Double Wyznacznik1 = Macierz1(0, 0)*Macierz1(1, 1)-Macierz1(1, 0)*Macierz1(0, 1) Wyznacznik2 = Macierz2(0, 0)*Macierz2(1, 1)-Macierz2(1, 0)*Macierz2(0, 1) Return Wyznacznik1 / Wyznacznik2 End Function Przykładowe wywołanie funkcji IlorazWyznacznikow demonstruje poniższy kod: Dim W1(,) As Integer = {{1, 2}, {3, 4}} Dim W2(,) As Integer = {{2, 4}, {6, 8}} MessageBox.Show(IlorazWyznacznikow(W1, W2)) Kod ten najpierw deklaruje dwie tablice W1 i W2 o wymiarach 2x2 i odpowiednie elementy tablic wartościami, po czym przekazuje je jako argumenty do funkcji IlorazWyznacznikow. Zakończenie działania aplikacji Każda aplikacja powinna dysponować możliwością jej poprawnego zakończenia. Można oczywiście skorzystać z przycisku zamykania aplikacji na belce tytułowej, ale co zrobić, jeżeli ze względu na styl okna jest on niedostępny? Aby poprawnie zakończyć działanie aplikacji możesz skorzystać z metody Exit obiektu Application. Poniższy kod demonstruje przykładową obsługę działania przycisku zakończ w aplikacji: Private Sub btnKOniec_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnKOniec.Click If messagebox.Show("Czy na pewno chcesz zakończyć działanie aplikacji?","Koniec?",MessageBoxButtons.YesNo,MessageBoxIcon.Question)=Dial ogResult.Yes then Application.Exit End Sub Uwaga: linie 1 i 2 oraz 3 i 4 powinny zostać zapisane jako jeden wiersz kodu Funkcje predefiniowane. Przedstawiona w jednym z odcinków klasa MessageBox pozwalała na wyświetlanie okien dialogowych. Interakcja z użytkownikiem sprowadzała się więc jedynie do naciśnięcia jednego z przycisków jakie zawierało wyświetlone okno dialogowe. Visual Basic .NET zawiera wiele funkcji predefiniowanych z których można budować kod aplikacji. Jedną z takich przykładowych funkcji jest funkcja InputBox. Funkcja ta służy do wyświetlenia okna dialogowego zawierającego tytuł, opis oraz pole tekstowe pozwalające na wprowadzenie wartości przez użytkownika. Funkcja ta jest więc kolejną metodą pozwalającą na pobieranie od użytkownika informacji w czasie działania aplikacji. Aby wywołać instrukcję InputBox należy skorzystać z następujących argumentów: Nazwa argumentu Prompt Title DefaultResponse XPos YPos Znaczenie Tekst jaki będzie zawierało okno dialogowe Tytuł okna dialogowego (napis na belce tytułowej) Domyślna odpowiedź. Jeśli argument ten jest określony, to po wyświetleniu okna dialogowego będzie ono już zawierało w polu tekstowym odpowiedzi wartość tego argumentu. Współrzędna X lewego górnego rogu okna (odległość od lewej krawędzi ekranu) Wartość domyślna Czy argument opcjonalny Nie Nazwa aplikacji Tak Pusty ciąg znaków Tak Połowa szerokości ekranu Jedna trzecia wysokości ekranu Tak Tak Wyświetlone okno będzie również zawierało przyciski OK i Cancel (Anuluj). Funkcja zwraca zmienną typu String zawierającą dane wprowadzone przez użytkownika. Jeśli użytkownik naciśnie przycisk Cancel, to funkcja zwróci zmienną typu String o zerowej długości. Znajomość funkcji predefiniowanych jest niezbędna do efektywnego tworzenia kodu. Na potrzeby ćwiczenia, jakie znajduje się na końću artykułu przedstawię jeszcze kolejną funkcję – DateDiff. Funkacja DateDiff zwraca liczbę wyrażającą ilość interwałów czasu, jaka upłynęła pomiędzy dwoma momentami w czasie. Rodzaj interwału (lata, miesiące, dni, godziny, minuty, sekundy) jak i określenie początku i końca przedziału czasu przekazywane są jako argumenty. Argument określający interwał może być przekazany jako jedna z wartości typu wyliczeniowego DateInterval lub jako zmienną typu String. Oprócz powyższych trzech argumentów do funkcji można również przekazać dwa argumenty opcjonalne: pierwszy dzień tygodnia oraz pierwszy dzień roku. Argumenty opcjonalne wpływają na zwracaną przez funkcję wartość w wypadku użycia interwałów tydzień i miesiąc. Do funkcji DateDiff można więc przekazać następujące argumenty: Nazwa argumentu Interval Date1 Date2 DayOfWeek WeekOfYear Znaczenie Interwał czasu, jaki ma zostać obliczony Początkowa data okresu Końcowa data okresu Pierwszy dzień tygodnia – domyślnie niedziela Pierwszy dzień roku – domyślnie 1 stycznia Przykładowe wartości argumentu Interval Typ wyliczeniowy (enumeracja) DateInterval.Year DateInterval.Month DateInterval.Weekday DateInterval.Day DateInterval.Hour Analogiczna zmienna typu String y m w d h Rodzaj zwracanego interwału rok miesiąc tydzień dzień godzina Zadanie końcowe tego artykułu polegać będzie na utworzeniu aplikacji, która zwraca liczbę dni życia użytkownika w oparciu o wprowadzoną przez niego datę urodzenia. Aby wykonać poniższe ćwiczenie musimy pobrać datę systemową. Można to zrobić przy pomocy przestrzeni nazw system, klasy datetime i metody now (System.DateTimeNow). Jesteśmy już gotowi do utworzenia projektućwiczenia. Ćwiczenie 1. Uruchom Visual Studio .NET 2. Wybierz szablon projektu Visual Basic .NET – Windows Application 3. Do formularza Form1 dodaj przycisk 4. Kliknij dwukrotnie na przycisku, aby otworzyć edytor kodu i utworzyć szkielet obsługi zdarzenie Click dla tego przycisku Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click End Sub 5. W ciele procedury obsługi przycisku (pomiędzy wiersze rozopoczynające się od Private Sub i End Sub) zadeklaruj zmienne DataDzis i DataUrodzenia. Obie zmienne powinny być typu Date. Zadeklaruj także zmienną Wynik typu Long. Liczba ta będzie przechowywała wartość zwracaną przez funkcję DateDiff. Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim dataDzis As Date Dim dataUrodzenia As Date Dim wynik As Long End Sub 6. Do zmiennej DataDzis przypisz bieżącą datę systemową Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim dataDzis As Date Dim dataUrodzenia As Date Dim wynik As Long dataDzis = System.DateTime.Now() End Sub 7. Do zmiennej DataUrodzenia podstaw datę pobraną od użytkownika przy pomocy funkcji InputBox. Pamiętaj, że dane zwrócone przez funkcję InputBox są typu String, a zmienna DataUrodzenia jest zmienną typu Date. Musisz więc odpowiednio skonwertować zwracaną wartość. Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim dataDzis As Date Dim dataUrodzenia As Date Dim wynik As Long dataDzis = Now() dataUrodzenia = _ CDate(InputBox("Podaj swoją datę urodzenia: ", _ "Data Urodzenia")) End Sub 8. Korzystając z funkcji DateDiff oblicz ile dni żyje użytkownik i wyświetl okno dialogowe ze stosowną informacją dla użytkownika. Private Sub Button1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles Button1.Click Dim dataDzis As Date Dim dataUrodzenia As Date Dim wynik As Long dataDzis = Now() dataUrodzenia = _ CDate(InputBox("Podaj swoją datę urodzenia: ", _ "Data Urodzenia")) wynik = DateDiff(DateInterval.Day, dataUrodzenia, _ dataDzis) MessageBox.Show(wynik) End Sub 9. Uruchom i sprawdź działanie aplikacji. Pamiętaj, że aplikacja nie jest odporna na błedy – wprowadzenie nieprawidłowej daty spowoduje błąd aplikacji. W kolejnym - ostatnim odcinku Akademii PC Kuriera poruszymy temat sterowania wykonaniem programu. Odcinek ten poświęcony będzie instrukcjom warunkowym oraz pętlom w języku Visual Basic .NET.