Atrybuty określają aktualny stan obiektu. Dla przykładowej klasy Samochód może to być:
- Prędkość
- Pojemność
- Czy drzwi są zamknięte?
- Czy światła są zapalone?
- Stan oleju
Spójrzmy na taką (bardziej praktyczną) instrukcję:
1 |
If gr_plik.IsOpen = True Then |
Mamy tutaj atrybut, zadeklarowany następująco w module klasy.
1 |
Public IsOpen As Boolean |
Przybiera wartość True, jeżeli plik jest otwarty lub False, jeżeli zamknięty. W metodzie otwierającej plik ustawiamy ten atrybut na True. Mogę więc napisać gdzieś:
1 2 3 |
If gr_plik.IsOpen = True Then MsgBox "Plik jest wciąż otwarty" End If |
Czy ma w takim razie sens poniższa instrukcja?
1 |
gr_plik.IsOpen = False |
Pozornie ma sens, jest jednak niebezpieczna. Ostatecznie zamykanie pliku nie może się ograniczać do ustawienia wartości jakieś zmiennej, plik należy zapisać. Z pomocą przychodzą właściwości, dzięki którym możemy tworzyć coś pomiędzy atrybutami a metodami. Poza klasą używa się je jak atrybuty. W środku klasy jest to jednak szereg wykonywanych instrukcji. Utworzę więc właściwość:
1 2 3 4 5 |
Property Let isOpen(iv_IsOpen As Boolean) If iv_IsOpen = False Then CloseFile End If End Property |
Dzięki temu powyższe przypisanie wartości False uruchamia instrukcje, które wywołują metodę CloseFile.
Wkrótce wyjaśnię to wszystko dokładniej. Przejdźmy więc do opisu używania atrybutów i właściwości
Atrybuty
Deklaruje się je jak każdą inną zmienną modułową. Mogą być prywatne i publiczne. Zadeklaruję dwie zmienne.
1 2 |
Private Wynagrodzenie As Double Public Nazwisko As String |
Atrybuty publiczne mogę używać poza klasą. Poniżej widać, że intelisense podpowiada mi atrybut publiczny. Prywatne oczywiście mogą być używane tylko w metodach tej klasy.
Właściwości
Tutaj wreszcie pojawia się jakaś nowość w stosunku do zwykłych modułów. Właściwości deklaruje się przy pomocy specjalnych słów kluczowych.
- Get – zwraca wartość lub obiekt
- Let – ustawia wartość
- Set – ustawia obiekt
1 2 3 4 5 6 7 8 |
Public Property Get wlasciwoscNazwa () As Type End Property Public Property Let wlasciwoscNazwa(argumentNazwa As Type ) End Property Public Property Set wlasciwoscNazwa(argumentNazwa As Type ) End Property |
Get
Definicja:
1 2 3 |
Property Get Nazwisko() As String Nazwisko = "Kowalski" End Property |
Użycie:
1 |
MsgBox gr_plik.Nazwisko |
Let
Definicja:
1 2 3 4 5 |
Private pstr_Nazwisko As String Property Let Nazwisko(iv_Nazwisko As String) pstr_Nazwisko = iv_Nazwisko End Property |
Użycie:
1 |
gr_plik.Nazwisko = "hej hej" |
Set
Definicja:
1 2 3 4 5 6 7 |
Option Explicit Private pref_Worksheet As Worksheet Property Set TargetWorksheet(iref_Worksheet As Worksheet) Set pref_Worksheet = iref_Worksheet End Property |
Użycie:
1 |
Set gref_DataWorksheet.TargetWorksheet = Worksheets.Add |
Każda z tych właściwości może występować samodzielnie, jednak z reguły występują parami Get i Let lub Get i Set.
Jak widać właściwość wcale nie musi nic zapisywać, czy odczytywać. Całkowicie prawidłowa (technicznie) jest taka właściwość.
1 2 3 4 5 6 7 |
Property Let isOpen(iv_IsOpen As Boolean) MsgBox "zapisuję" End Property Property Get isOpen() As Boolean MsgBox "otwieram" End Property |
Można użyć ją tak:
1 2 3 4 5 |
Private col_Countries() As Collection Public Function Count() As Long Count = col_Countries.Count End Function |
Dzięki temu, zawsze Count będzie zwracać ilość krajów, nawet, jeżeli kolekcję zmienimy na tablicę:
1 2 3 4 5 |
Private arr_Countries() As String Public Function Count() As Long Count = UBound(arr_Countries) + 1 End Function |
Używanie razem
Atrybuty i właściwości często używa się razem. Ustawiamy atrybuty jako prywatne, a właściwości służą wtedy do kontroli dostępu. Poniżej upewniam się, czy zapisywane nazwisko nie jest dłuższe niż 30 znaków.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Option Explicit Private pstr_Nazwisko As String Const gc_NazwiskoMaxLen As Integer = 30 Property Let Nazwisko(iv_Nazwisko As String) If Len(iv_Nazwisko) <= gc_NazwiskoMaxLen Then pstr_Nazwisko = iv_Nazwisko End If End Property Property Get Nazwisko() As String Nazwisko = pstr_Nazwisko End Property |