Kurs VBA – Klasy – Atrybuty i właściwości

Zastanawiałem się przez jakiś czas czy atrybuty i właściwości podzielić na dwa osobne posty. Występują one bardzo często razem i poza klasą używa się je tak samo, jednak należy pamiętać, że są to dwie osobne funkcjonalności klas.

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ę:

If gr_plik.IsOpen = True Then

Mamy tutaj atrybut, zadeklarowany następująco w module klasy.

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ś:

If gr_plik.IsOpen = True Then
   MsgBox "Plik jest wciąż otwarty"
End If

Czy ma w takim razie sens poniższa instrukcja?

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ść:

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.

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.

  1. Get – zwraca wartość lub obiekt
  2. Let – ustawia wartość
  3. Set – ustawia obiekt
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

Kilka przykładów:

Get

Definicja:

Property Get Nazwisko() As String
    Nazwisko = "Kowalski"
End Property

Użycie:

MsgBox gr_plik.Nazwisko
Let

Definicja:

Private pstr_Nazwisko As String

Property Let Nazwisko(iv_Nazwisko As String)
  pstr_Nazwisko = iv_Nazwisko
End Property

Użycie:

gr_plik.Nazwisko = "hej hej"
Set

Definicja:

Option Explicit

Private pref_Worksheet As Worksheet

Property Set TargetWorksheet(iref_Worksheet As Worksheet)
  Set pref_Worksheet = iref_Worksheet
End Property

Użycie:

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ść.

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:

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ę:

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.

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

 

Metody Spis treści Konstruktur i destruktor

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.