Programowanie zaawansowane

Slides:



Advertisements
Podobne prezentacje
C++ wykład 2 ( ) Klasy i obiekty.
Advertisements

C++ wykład 4 ( ) Przeciążanie operatorów.
Język C/C++ Funkcje.
Deklaracje i definicje klas w C++ Składowe, pola, metody Konstruktory
Programowanie obiektowe
Programowanie obiektowe
POWIAT MYŚLENICKI Tytuł Projektu: Poprawa płynności ruchu w centrum Myślenic poprzez przebudowę skrzyżowań dróg powiatowych K 1935 i K 1967na rondo.
Wzorce.
Prowadzący: mgr inż. Elżbieta Majka
Liczby pierwsze.
Domy Na Wodzie - metoda na wlasne M
PROGRAMOWANIE STRUKTURALNE
Podstawy informatyki Wirtotechnologia – Wskaźniki i referencje
Podstawy informatyki Powtórka Grupa: 1A Prowadzący: Grzegorz Smyk
Struktury.
Tablice.
Dziedziczenie i jego rodzaje
C++ wykład 2 ( ) Klasy i obiekty.
Zasady zaliczenia Warunki uzyskania zaliczenia:
Wykonawcy:Magdalena Bęczkowska Łukasz Maliszewski Piotr Kwiatek Piotr Litwiniuk Paweł Głębocki.
Pakiety w Javie Łukasz Smyczyński (132834). Czym są pakiety? Klasy w Javie są grupowane w pewne zbiory zwane pakietami. Pakiety są więc pewnym podzbiorem.
Podstawy programowania II
Wyrażenia algebraiczne
T: Różnice pomiędzy programowaniem strukturalnym a obiektowym
KOLEKTOR ZASOBNIK 2 ZASOBNIK 1 POMPA P2 POMPA P1 30°C Zasada działanie instalacji solarnej.
Andrzej Repak Nr albumu
Java – coś na temat Klas Piotr Rosik
Dziedziczenie Maciek Mięczakowski
Inicjalizacja i sprzątanie
Programowanie obiektowe Wykład 3 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/21 Dariusz Wardowski.
Programowanie obiektowe Wykład 6 dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14 Dariusz Wardowski.
Farseer Physics Engine. Farseer Physics Engine jest silnikiem fizycznym napisanym dla platformy.NET. Został on zainspirowany przez silnik Box2D znany.
1. Pomyśl sobie liczbę dwucyfrową (Na przykład: 62)
Przekazywanie parametrów do funkcji oraz zmienne globalne i lokalne
Programowanie obiektowe 2013/2014
ZWIĄZKI MIĘDZY KLASAMI KLASY ABSTRAKCYJNE OGRANICZENIA INTERFEJSY SZABLONY safa Michał Telus.
Prasek Aneta, Skiba Katarzyna. Funkcje stałe const to takie funkcje, które nie mogą modyfikować stanu obiektu. Oznacza to, że funkcja stała nie może zmieniać.
Kurs języka C++ – wykład 9 ( )
EcoCondens Kompakt BBK 7-22 E.
Programowanie w języku C++
Programowanie w języku C++
User experience studio Użyteczna biblioteka Teraźniejszość i przyszłość informacji naukowej.
Obliczalność czyli co da się policzyć i jak Model obliczeń sieci liczące dr Kamila Barylska.
Testogranie TESTOGRANIE Bogdana Berezy.
Programowanie strukturalne i obiektowe C++
Model obiektowy bazy danych
Dr hab. Renata Babińska- Górecka
Kurs języka C++ – wykład 4 ( )
Współrzędnościowe maszyny pomiarowe
Elementy geometryczne i relacje
Programowanie zaawansowane Zaawansowane konstrukcje języka C#
Waldemar Bartyna Pytania egzaminacyjne 1.
Waldemar Bartyna 1 Programowanie zaawansowane LINQ to XML.
Obiekty COM Przemysław Buczkowski. Plan prezentacji 1.Wprowadzenie do COM 2.Historia standardu 3.Jak działa COM 4.Interface IUknown 5.Paradygmaty COM.
Łukasz Bieszczad Mateusz Gałązka Karol Włodarek
Programowanie Zaawansowane
Zestaw pytań nr. 3 Typy generyczne Wyjątki OPRACOWALI: JAKUB GRYCZEWSKIKINGA ROSA DANIEL KAPTEJNYWOJCIECH ŁĘCZYCKI
Waldemar Bartyna Pytania egzaminacyjne 1.
ASP.NET Dostęp do bazy danych z poziomu kodu Elżbieta Mrówka-Matejewska.
Oprogramowanie w eksperymentach fizyki Wykład 3, Paweł Staszel.
Programowanie Obiektowe – Wykład 6
Programowanie Obiektowe – Wykład 9
Klasy, pola, obiekty, metody. Modyfikatory dostępu, hermetyzacja
(według:
Delegaty Delegat to obiekt „wiedzący”, jak wywołać metodę.
Programowanie Obiektowe – Wykład 2
Haskell Składnia funkcji.
PGO Dziedziczenie Michail Mokkas.
PGO Przeciążanie metod i konstruktorów
Zapis prezentacji:

Programowanie zaawansowane Delegaty

Plan wykładu Delegaty Zdarzenia Metody anonimowe Operator lamda

Delegaty

Spojrzenie w przeszłość W Windows API często korzystano ze wskaźników do funkcji w celu tworzenia elementów zwanych funkcjami wywołań zwrotnych, albo po prostu wywołaniami zwrotnymi (ang. callback). Stosowanie tego mechanizmu pozwalało programistom na konfigurowanie wybranej funkcji tak, aby była ona w stanie wywoływać inne, dynamicznie przekazywane, funkcje. Przy pomocy tego podejścia radzono sobie z obsługą kliknięcia przycisku, poruszenia myszką, wyboru opcji z menu i innymi przykładami dwukierunkowej komunikacji między dwoma bytami programistycznymi.

Spojrzenie w przeszłość c. d. Standardowe funkcje wywołań zwrotnych (rodem z języka C) reprezentują jedynie adres w pamięci. Wywołania zwrotne mogłyby zawierać informacje związane z bezpieczeństwem typów, takie jak ilość i typ parametrów oraz typ zwracanej wartość przez metodę, na którą wskazują. Z powodu braku tych informacji, standardowe wywołania zwrotne były często przyczyną błędów i zawieszania się aplikacji. Nie zmienia to faktu, że sam mechanizm wywołań zwrotnych jest bardzo użyteczny.

Powrót w przyszłość Na platformie .NET, stosowanie wywołań zwrotnych jest nadal możliwe, a ich funkcjonalność została zrealizowana w bardziej bezpieczny i obiektowo zorientowany sposób. Delegat to obiekt zapewniający bezpieczeństwo typu, wskazujący na metodę (lub zbiór metody), które mogą być wywołane w późniejszym czasie. Delegat przechowuje następujące informacje: Adres metody, którą może wywołać, Ilość i typ argumentów metody, Typ wartości (lub jej brak) zwracanej przez daną metodę.

Cechy delegatów W odróżnieniu od wskaźników do funkcji w C i C++, delegaty mogą wskazywać na statyczne i instancyjne metody. Po stworzeniu delegata i dostarczeniu potrzebnych informacji, może on dynamicznie wywoływać metody, przekazywane do niego w czasie wykonania programu. Każdy delegat jest automatycznie wyposażany w możliwość wywoływania metod w sposób synchroniczny i asynchroniczny. Upraszcza to w dużym stopniu wywoływanie metod w drugoplanowym wątku, bez konieczności tworzenia i utrzymywania obiektu wątku.

Definiowanie delegata Delegaty tworzymy za pomocą słowa kluczowego delegate. Możemy mu nadać dowolną nazwę. Definiowany delegat musi odpowiadać sygnaturze metod, które ma przechowywać. Na przykład, chcąc stworzyć delegat o nazwie BinaryOp, który może wskazywać na dowolną metodę przyjmującą dwa parametru typu int i zwracającą typ int, zapiszemy następującą definicję:

Klasy związane z delegatami Kompilator C#, przetwarzając definicję delegata, automatycznie generuje klasę dziedziczącą po klasie System.MulticastDelegate. Klasa ta, razem z bazową klasą System.Delegate, zapewnia wymaganą infrastrukturę pozwalającą delegatom na przechowywanie listy metod do późniejszego wywołania.

Klasy związane z delegatami c. d. Wygenerowana przez kompilator klasa posiada trzy metody: Metoda Invoke() służy do wywoływania każdej z metod przechowywanych w delegacie w sposób synchroniczny (wywołujący musi poczekać na zakończenie się wywoływanej metody). Metoda ta jest wywoływana niejawnie. Metody BeginInvoke() i EndInvoke() powalają na wywołanie metody w sposób asynchroniczny w osobnym wątku wykonania. Najczęstszym powodem korzystania z wątku jest przerzucenie do niego wykonania funkcji zajmującej dużo czasu. Dzięki delegatom, mamy taką możliwość bez ręcznego tworzenia obiektu wątku.

Jak kompilator generuje klasę delegata? Parametry i wartość zwracana przez metodę Invoke() dokładnie odpowiadają definicji delegata. Parametry metody BeginInvoko() odpowiadają parametrom delegata, Oprócz nich, metoda ta zawsze przyjmuje dwa dodatkowe parametry (AsyncCallback i object) w związku z asynchronicznym wywołaniem. Wartość zwracana przez metodę EndInvoke() odpowiada tej zdefiniowanej w delegacie. Dodatkowo przyjmuje pojedynczy parametr – obiekt klasy implementującej interfejs IAsyncResult.

Jak kompilator generuje klasę delegata? c. d. W kolejnym przykładzie, załóżmy, że chcemy zdefiniować delegat, który może przechowywać i wywoływać metody zwracające obiekt klasy System.String i przyjmujące trzy argumenty typu System.Boolean.

Jak kompilator generuje klasę delegata? c. d. 2 Delegaty mogą również wskazywać na metody przyjmujące dowolną liczbę parametrów z atrybutami ref i out. Dwie pierwsze metody zostały wygenerowane zgonie z poprzednimi przykładami. Różnica polega na tym, że metoda EndInvoke() została rozszerzona o parametry z atrybutami ref i out.

Ogólna zasada generowania klasy delegata Zasadę tą obrazuje następujący pseudo kod:

Klasa System.Delegate Klasa bazowa System.Delegate posiada, między innymi, następujące składowe.

Klasa System.MulticastDelegate Każda klasa wygenerowana przez kompilator dziedziczy po klasie System.MulticastDelegate.

Wspólne składowe delegatów W swoim kodzie, nie możemy dziedziczyć po tych dwóch klasach. Powoduje to błąd kompilacji. Jednakże, używając słowa kluczowego delegate, pośrednio tworzymy klasę dziedziczącą po System.MulticastDelegate. Kilka składowych wspólnych dla wszystkich delegatów to: Method – Właściwość ta zwraca obiekt klasy System.Reflection.MethodInfo, która reprezentuje szczegółowe informacje o metodzie przechowywanej przez delegata. Target – Właściwość ta zwraca informację o typie, w którym została zdefiniowana przechowywana metoda, jeżeli jest ona zdefiniowana na poziomie obiektu. W przeciwnym razie zwraca null, co oznacza, że jest to metoda statyczna.

Wspólne składowe delegatów c. d. Combine() – Ta statyczna metoda dodaje wskazaną metodę do listy przechowywanej przez delegata. W C# metoda ta jest wyzwalana przez użycie przeładowanego operatora +=. GetInvocationList() – Metoda ta zwraca tablicę obiektów typu System.Delegate, reprezentujących poszczególne metody do wywołania. Remove() , RemoveAll() – Te statyczne metody usuwają wskazaną metodę (lub wszystkie) z listy wywołań delegata.

Najprostszy przykład użycia delegata

Najprostszy przykład użycia delegata c. d. W przykładzie zdefiniowaliśmy delegata, który może wskazywać na metody przyjmujące dwa parametry liczbowe i zwracające liczbę. Nazwy metod są nieistotne. Jeżeli chcemy umieścić docelową metodę w delegacie, po prostu przekazujemy ją poprzez konstruktor. Metodę, na którą wskazuje nasz delegat wywołujemy w sposób przypominający bezpośrednie wywołanie funkcji. W rzeczywistości, wywoływana jest niejawnie metoda Invoke(). Możemy równie dobrze wywołać ją jawnie.

Najprostszy przykład użycia delegata c. d. 2 Delegaty na platformie .NET zapewniają bezpieczeństwo typów. Dlatego też próba przekazania do delegata metody nie odpowiadającej zadanemu wzorcowi (sygnaturze metody) spowoduje wyświetlenie błędu podczas kompilacji. Załóżmy, że klasa SimpleMath posiada jeszcze jedną metodę. Próba przekazania jej do delegata spowoduje błąd w czasie kompilacji (metoda nie odpowiada sygnaturze delegata).

Pozyskiwanie informacji o metodach Metoda wyświetlająca informacje o metodach przechowywanych w podanym delegacie. Po odpowiedniej zmianie metody main() w naszym przykładzie, otrzymamy następujący rezultat. Dlaczego?

Pozyskiwanie informacji o metodach c. d. Po zmianie metod ze statycznych na wywoływane z poziomu instancji, nadal możemy przekazywać je do delegata. Informacje o metodzie instancyjnej zawierają informacje o typie, w którym zostały zdefiniowane (właściwość Target).

Dodanie delegatów do klasy Car Aby zastąpić komunikację z klasą Car za pomocą interfejsów wywołań zwrotnych na delegaty należy: Zdefiniować nowy typ delegata, który wyśle powiadomienie do wywołującego, Zadeklarować w klasie Car zmienne odpowiednich typów delegatów, Stworzyć funkcje pomocnicze, które pozwolą wywołującemu na przekazanie metod do zadeklarowanych zmiennych (delegatów), Zaktualizować metodę Accelerate(), tak aby wywoływała metody na liście delegata w odpowiedniej sytuacji.

Dodanie delegatów do klasy Car c. d.

Dodanie delegatów do klasy Car c. d. 2

Dodanie delegatów do klasy Car c. d. 3

Multicasting Aby zapewnić możliwość rejestrowania wielu metod w jednej zmiennej delegata (i tym samym możliwość wywoływania wielu metod jednocześnie – ang. multicasting), należy odpowiednio zmienić implementację metod pomocniczych. Poprzez użycie przeładowanego operatora +=, wywołują one metodę Combine() dołączając wskazaną metodę do listy wywołań delegata.

Multicasting c. d.

Usunięcie metody z listy wywołań Aby wywołujący mógł usunąć metodę z listy wywołań, należy dostarczyć odpowiednie metody pomocnicze. Korzystają one z przeładowanego operatora -=, który powoduje niejawne wywołanie metody Remove().

Usunięcie metody z listy wywołań c. d. W poniższym przykładzie usunięcia metody, pamiętamy zmienną delegata, którą później przekazujemy do usunięcia. Możliwe jest również ponowne zdefiniowania delegata na bazie metody, którą chcemy usunąć z listy. Tak więc przetrzymywanie zmiennej z takim delegatem nie jest konieczne.

Bardziej złożony przykład Tradycyjnie zaczynamy od odpowiedniej modyfikacji klasy Car.

Bardziej złożony przykład c. d. Do klasy Car dodajemy również definicję kolejnego typu delegata. CarMaintenanceDelegate może przechowywać i wywoływać dowolną metodę przyjmującą jako parametr obiekt klasy Car i nie zwracającą żadnej wartości.

Bardziej złożony przykład c. d. 2 Dodajemy definicję klasy, przechowującej listę samochodów za pomocą kolekcji generycznej. Na kolejnym slajdzie znajduje się definicja metody tej klasy, która jako argument przyjmuje wskazany typ delegata.

Bardziej złożony przykład c. d. 3

Bardziej złożony przykład c. d. 4 Dodajemy klasę definiującą metody, które będą przechowywane i wywoływane przez delegata klasy Car.

Bardziej złożony przykład c. d. 5 Garaż deleguje całą pracę do działu obsługi

Bardziej złożony przykład c. d. 6

Kowariancja delegatów Do tej pory, przykładowe delegaty zwracały proste wartości liczbowe. Mogą one również zwracać złożone klasy należące do różnych hierarchii dziedziczenia. Załóżmy, że mamy klasę Car i dziedziczącą po niej klasę SportsCar. Utwórzmy delegat, który wywołuje utworzenie obiektu.

Kowariancja delegatów c. d.

Kowariancja delegatów c. d. 2

Kowariancja delegatów c. d. 3 Kowariancja pozwala na przekazywanie do delegata metod, których typ zwracanej wartości nie jest identyczny z sygnaturą delegata, ale jest potomnym w stosunku do zwracanego typu zdefiniowanego w tym delegacie. Na podobnej zasadzie działa kontrkowariancja, z tym, że dotyczy ona argumentów metod przekazywanych do delegata.

Generyczne delegaty

Generyczne delegaty c. d.

Zdarzenia

Niedogodności związane z delegatami Delegaty są konstrukcjami umożliwiającymi dwukierunkową komunikację między obiektami w pamięci. Jednak wykorzystywanie ich w surowej postaci pociąga za sobą kilka niedogodności. Aby posłużyć się delegatem musimy: Zdefiniować typ delegata, Zadeklarować potrzebne zmienne tego typu, Stworzyć własne metody pomocnicze pozwalające na rejestrowanie i wyrejestrowywanie metod z delegatów w celu zachowania hermetyzacji. W przypadku zadeklarowania zmiennej delegata jako publicznej, ryzykujemy możliwości manipulacji na liście wywołań przez potencjalnie niebezpieczny kod w obiektach korzystających z naszego delegata.

Słowo kluczowe event Rozwiązaniem tych niedogodności jest słowo kluczowe event. Gdy kompilator napotka na to słowo, automatycznie generuje metody do rejestracji i wyrejestrowywania metod oraz zmienną do przechowywania listy tych metod. Zmienne te są zawsze deklarowane jako prywatne. W sumie, słowo kluczowe event (zdarzenie) jest po prostu syntaktycznym skrótem, który oszczędza czas programiście (podobnie jak w przypadku właściwości automatycznych).

Definiowanie zdarzenia Definiowanie zdarzenia to dwukrokowy proces: Najpierw definiujemy odpowiedni typ delegata, Następnie definiujemy zdarzenie skojarzone z tym delegatem.

„Odpalanie” zdarzeń

Rejestracja metod obsługujących zdarzenie

Korzystajmy z pomocy środowiska Przy dodawaniu metod do zdarzeń możemy skorzystać z pomocy środowiska. Po wpisaniu operatora +=, system pomocy podpowiada nam, jakiego rodzaju delegat jest obsługiwany przez dane zdarzenie. Po kliknięciu tabulatora, system pomocy doda odpowiedni konstruktor i teraz z kolei proponuje nam nazwę metody obsługującej dane zdarzenie. Jeżeli ponownie wciśniemy tabulator, zostanie wygenerowany szkielet metody o proponowanej nazwie.

Wzorzec zdarzenia Zdarzenia w bibliotece klas bazowych .NET definiowane są zgodnie ze wspólnym standardem. Delegaty przez nie obsługiwane przyjmują zawsze dwa parametry: Pierwszym jest System.Object reprezentujący referencje do obiektu, który wywołał dane zdarzenie. Drugi dziedziczy po typie System.EventArgs i reprezentuje informacje o aktualnym zdarzeniu.

Wzorzec zdarzenia c. d. W przypadku prostych zdarzeń można bezpośrednio przekazać obiekt klasy EventArgs. W innych przypadkach należy stworzyć własną klasę dziedziczącą po klasie EventArgs.

Wzorzec zdarzenia c. d. 2 Obecnie, definicja naszego delegata będzie wyglądać następująco: Odpalenie zdarzenia związanego z powyższym delegatem

Strona wywołującego I odpowiednio dopasowujemy metody obsługujące zdarzenia po stronie wywołującego.

Generyczny delegat EventHandler<T> Skoro tyle delegatów przyjmuje jako parametr obiekt klasy System.Object oraz potomka klasy EventArgs, możemy jeszcze bardziej uprościć nasz kod poprzez wykorzystanie generycznego delegata EventHandler<T>, gdzie T jest niestandardową klasą dziedziczącą po EventArgs.

Generyczny delegat EventHandler<T> c. d.

Metody anonimowe i operator lambda

Problem Metody służące do obsługi zdarzeń nie są przeważnie wykorzystywane w innym miejscu aplikacji.

Rozwiązanie

Metody anonimowe Możliwe jest powiązanie delegata bezpośrednio z blokiem kodu w momencie rejestracji obsługi zdarzenia. Taki blok kodu jest nazywany metodą anonimową. Składnia metody anonimowej wygląda następująco: Z metody anonimowej mamy dostęp do zewnętrznych zmiennych (oprócz zmiennych oznaczonych atrybutem ref i out.

Konwersja grup metod Kompilator obsługuje również konwersję grup metod. Dzięki niej możemy do zdarzenia dodać od razu nazwę metody obsługującej dane zdarzenie (bez koniczności tworzenia delegata). W razie konieczności, samą nazwę metody można rzutować na odpowiedni typ delegata.

Operator lambda Operator lamba (=>) pozwala jeszcze bardziej skrócić zapis metod anonimowych.

Operator lambda c. d. Przed samym operatorem podajemy listę argumentów (typy są nieobowiązkowe) w nawiasach. W przypadku bezargumentowej metody wstawiamy przed operatorem same nawiasy: (() => … ). Po operatorze, umieszczamy blok instrukcji do wykonania, np.:

Dziękuję za uwagę