OOP - programowanie zorientowane obiektowo w VB.NET Janusz Górczyński
Agenda Wprowadzenie Przestrzenie nazw, klasy, moduły Typy dostępu Współdzielone funkcje Przeciążenie Dziedziczenie Przesłanianie Polimorfizm Interfejsy Właściwości Konstruktory
Wprowadzenie Metoda programowania za pomocą tworzenia modeli obiektów nazywana jest programowaniem obiektowym. W środowisku .NET Framework wszystkie wykorzystywane w aplikacjach komponenty (okna, przyciski, urządzenia wejścia-wyjścia) oraz dane (pliki, bazy danych, ustawienia konfiguracyjne) przedstawiane są jako obiekty. VB.NET obsługuje cztery podstawowe mechanizmy programowania obiektowego: Abstrakcję – czyli możliwość tworzenia kodu w postaci „czarnej skrzynki”, czyli tworzenia abstrakcyjnej reprezentacji danej koncepcji w programie. Np. klasa CStudent jest abstrakcyjną reprezentacją rzeczywistego studenta.
Wprowadzenie (2) Hermetyzację – jest to koncepcja oddzielenia interfejsu od implementacji. Interfejs to zestaw publicznych metod utworzonych w klasie, poprzez ten zestaw korzystamy z obiektów. Jeżeli interfejs pozostanie spójny (te samy nazwy metod i ich argumenty), to sposób korzystania z obiektów nie ulegnie zmianie niezależnie od sposobu wyrażenia w kodzie metod (czyli od implementacji). Hermetyzacja pozwala na ukrycie szczegółów wewnątrz klasy. Polimorfizmu – związanego z tworzeniem funkcji, która operuje na obiektach więcej niż jednej klasy. Przykładowo klasy CStudnet i CWykladowca mogą mieć właściwość ImieNazwisko, można napisać funkcję, która wywołuje tę właściwość z jednej lub drugiej klasy. Dziedziczenie – czyli możliwość przejęcia przez daną klasę interfejsu i operacji z istniejącej klasy.
Przestrzenie nazw, klasy, moduły W VB.NET klasy i inne struktury danych o podobnym przeznaczeniu zgrupowane są w postaci tzw. przestrzeni nazw. Najprostszym sposobem wykorzystania danej klasy jest zaimportowanie jej przestrzeni nazw. Słowo kluczowe Imports jest używane do zaimportowania danej przestrzeni nazw do naszego projektu. Środowisko .NET Framework dostarcza wielu bardzo przydatnych klas zgromadzonych w różnych przestrzeniach nazw. Jedną z nich jest System Imports System – to instrukcja pozwalająca na korzystanie z klas zebranych w tej przestrzeni
Przykładowa klasa CStudent
Typy dostępu Obiekty w klasach mogą mieć jeden z czterech typów dostępu: Public, Private, Protected i Friend Obiekty poprzedzone słowem Public są dostępne w instancji klasy Obiekty poprzedzone słowem Private mogą być dostępne tylko wewnątrz danej klasy Słowo kluczowe Protected ma podobne znaczenie jak Private, ale jest używane w klasach bazowych po to, aby ich obiekty były dostępne dla klas potomnych Słowo kluczowe Friend udostępnia obiekty tylko wewnątrz danego projektu.
Współdzielone funkcje Obiekty klas, zarówno funkcje jak i zmienne zadeklarowane z użyciem słowa kluczowego Shared stają się dostępne bez konieczności tworzenia instancji danej klasy. Przykładowo deklaracja Public Shared Function fDataKrotka() w klasie CStudent spowoduje, że możemy się odwołać do tej funkcji poprzez podanie jej nazwy kwalifikowanej (pełnej nazwy z podaniem przestrzeni nazw i klasy, w której jest utworzona) Przykład wywołania takiej funkcji: Console.WriteLine(WSZiM.CStudent.fDataKrotka(Now()))
Przykład funkcji współdzielonej, definicja
Przykład funkcji współdzielonej, wywołanie
Przeciążenie (ang. Overloading) Jest to technika pozwalająca na przekazanie do funkcji czy procedury klasy parametrów różnych typów. Przykładowo, chcemy utworzyć funkcję sumującą dwa argumenty, mogą to być np. liczby całkowite, liczby pojedynczej precyzji czy też teksty. Rozwiązaniem jest utworzenie trzech funkcji o tej samej nazwie, ale różnych typach argumentów. Warunkiem koniecznym przeciążenia metody klasy jest poprzedzenie jej definicji słowem kluczowym Overloads. Przykład definicji pokazany jest na kolejnym slajdzie
Definicja metody z użyciem Overloads
Przykład wykorzystania przeciążenia
Dziedziczenie (ang. Inherits) Jest to właściwość pozwalająca na tworzenie klas potomnych dziedziczących metody (interfejs) klasy bazowej. Do poinformowania systemu, że tworzymy klasę potomną służy słowo kluczowe Inherits. Informacja o dziedziczeniu jest zawsze pierwszą instrukcją w module klasy potomnej. Public Class CDane Inherits CForStorageSub dalsze instrukcje klasy potomnej End Class Metody klasy bazowej są dostępne w klasie potomnej po użyciu słowa kluczowego MyBase
Dziedziczenie (Inherits) (2) Metody klasy bazowej mogą być poprzedzone kwalifikatorem dostępu Protected, wtedy są dostępne jedynie dla klas potomnych Definicja klasy może być poprzedzona słowem kluczowym MustInherit, jeżeli tak będzie, do taka klasa nie może być wykorzystana do utworzenia instancji klasy. Jej przeznaczeniem jest funkcjonowanie wyłącznie jako klasa bazowa dla innych klas. Słowo kluczowe NotInherit oznacza z kolei, że dana klasa nie może być klasą bazową dla innych klas. W VB.NET klasa potomna może dziedziczyć jedynie po jednej klasie bazowej
Dziedziczenie – przykład klasy bazowej
Dziedziczenie, przykład klasy potomnej
Dziedziczenie, słowo kluczowe MyBase
Nadpisanie (ang. Overriding) Z założenia klasa potomna dziedziczy metody i właściwości klasy bazowej. Jeżeli z jakiś powodów odziedziczona właściwość czy metoda ma się zachowywać inaczej w klasie potomnej, to musi być nadpisana. Robimy to tworząc w klasie potomnej nową implementację tej metody czy właściwości. Będzie to możliwe tylko wtedy, gdy w klasie bazowej taka metoda (właściwość) będzie poprzedzona słowem kluczowym Overridable. Jej implementacja w klasie potomnej musi być oznaczona słowem Overrides.
Przykład nadpisania
Polimorfizm Zdolność do zmiany implementacji metody czy właściwości. Dzięki temu ta sama metoda czy właściwość (dokładniej o tej samej nazwie) może realizować inną akcję zależnie od typu instancji wywołującej tą metodę czy właściwość.
Polimorfizm oparty o dziedziczenie (1)
Polimorfizm oparty o dziedziczenie (2)
Polimorfizm oparty o dziedziczenie (3) W pokazanym przykładzie procedura ShowTax akceptuje parametr Item typu BaseTax, ale akceptuje także klasy dziedziczące po klasie BaseTax. Jest to zaleta tego rozwiązania, oznacza bowiem, że możemy tworzyć nowe klasy potomne po klasie bazowej BaseTax i dalej korzystać z procedury ShowTax bez konieczności modyfikacji jej kodu.
Polimorfizm oparty o interfejs (1) Interfejsy zabezpieczają inną możliwość wykorzystania polimorfizmu w VB.NET Interfejsy opisują metody i właściwości tak jak klasy, ale bez klas. Interfejsy nie zawierają implementacji. Dla wykorzystania mechanizmu polimorfizmu musimy inaczej zaimplementować interfejs w różnych klasach. Aplikacja klienta korzysta z tych implementacji w analogiczny sposób. Prześledzimy ten problem na przykładzie obliczania pól trójkątów i prostokątów.
Polimorfizm oparty o interfejs (2) W module aplikacji (poza klasą) tworzymy kod definiujący interfejs. Utworzymy teraz moduł klasy zawierający definicje dwóch klas, jedna będzie reprezentować abstrakcyjny trójkąt, druga prostokąt, każda z nich będzie zawierała implementację interfejsu IPowierzchnia.
Polimorfizm oparty o interfejs (3)
Polimorfizm oparty o interfejs (4)
Polimorfizm oparty o interfejs (5) Wywołanie procedury TestInterface daje kolejno takie efekty:
Interfejsy Interfejsy, podobnie jak klasy, definiują zestaw właściwości, metod i zdarzeń, ale w odróżnieniu od klas, nie zawierają implementacji. Interfejsy są implementowane w klasach jako wydzielone fragmenty kodu. Definicja interfejsu zawarta jest między słowami kluczowymi Interface i End Interface Pozostała część kodu może być zadeklarowana jako Event, Sub, Function czy Property
Interfejsy – definicja i implementacja Przykłady definicji interfejsu Interface ISample Event PotwierdzenieZmiany(ByVal sukces As Boolean) Property Podzial() As String Function GetID() As Integer End Interface Class CSample Implements ISample Public Event PotwierdzenieZmiany(ByVal sukces As Boolean) _ Implements ISample.PotwierdzenieZmiany Private mPodzial As String Public Property Division() As String Implements ISample.Podzial Get Return mPodzial End Get Set(ByVal value As String) mPodzial = value RaiseEvent PotwierdzenieZmiany(True) End Set End Property
Interfejsy – definicja i implementacja (2) Private mID As Integer Public Function GetID() As Integer _ Implements ISample.GetID Return mID End Function Public Sub New(ByVal podzial As String, _ ByVal ID As Integer) mPodzial = podzial mID= ID End Sub End Class
Właściwości Zapewniają one wygodny mechanizm odczytu, zapisu i obliczania wartości zmiennych prywatnych klasy. Class WskaznikPostepu Private mPostep As Integer Public Property Postep() As Integer Get Postep = mPostep End Get Set(ByVal value As Integer) If value < 0 Then mPostep = 0 ElseIf value > 100 Then mPostep = 100 Else mPostep = value End if End Set End Property End Class
Właściwości (2) Do właściwości odwołujemy się tak, jakby była zmienną składową, jednak w momencie przypisania wykonywany jest kod z odpowiedniego bloku (Get lub Set). Dim wsk As WskaznikPostepu = _ New WskaznikPostepu wsk.Postep = -10 System.Console.Write("Postęp: {0}", wsk.Postep) W tym wypadku w konsoli pojawi się komunikat: Postęp: 0 W momencie przypisania do właściwości Postep wartości -10, wywołany zostaje blok Set tej właściwości, który koryguje nieprawidłową wartość. W prywatnej zmiennej składowej zapisywana jest liczba 0. W następnej linii, podczas pobierania wartości właściwości, kod bloku Get zwraca wartość zapisaną w składowej prywatnej
Konstruktor Każda klasa posiada specjalną funkcję składową, zwaną konstruktorem. Funkcja ta wywoływana jest podczas tworzenia nowego egzemplarza klasy. W momencie inicjowania obiektu klasy za pomocą słowa kluczowego New wywoływany jest odpowiedni stworzony przez nas konstruktor, a jeśli go nie ma, to automatycznie utworzony konstruktor domyślny. Konstruktor służy do ustawienia początkowych wartości zmiennych prywatnych (składowych) obiektu Public Class CSamochod Private mKolor As String Public Sub New(ByVal KolorFabryczny As String) mKolor = KolorFabryczny End Sub End Class