V prejšnjem blogu sem omenil, da nam pri ščitenju resursov lahko pomagajo objekti in zdaj je čas, da si ogledamo kako.
Napišimo torej skrajno preprost objekt, ki ima samo konstruktor, destruktor ter inicializacijsko funkcijo, ki mu postavi ime, da mu lažje sledimo (poimenujmo ga objSciti):
Option Explicit Private ime As String Private Sub Class_Initialize() Debug.Print "NOV " End Sub Private Sub Class_Terminate() Debug.Print "BRIŠEM "; ime End Sub Public Sub init(aime As String) ime = aime Debug.Print " POSTAVIM "; ime End Sub
Uporabimo ga v preprosti proceduri:
Sub Proc() Dim a As New objSciti a.init "prvi" End Sub
Če proceduro izvedemo, dobimo sledeč rezultat:
NOV POSTAVIM prvi BRIŠEM prvi
Če funkcijo pogledamo, nam je jasno, da izpis niza ‘NOV’ povzroči prva vrstica kode, izpis niza ‘POSTAVIM prvi’ povzroči druga vrstica kode… Kaj pa izpis tretjega niza? Tretji niz pa izpiše destruktor, ki ga VBA pokliče sam ob zaključku procedure.
Malce nižje bomo sicer spoznali tudi, da pravzaprav prvi dve vrstici izpiše funkcija ‘init’, a to zdajle niti ni pomembno.
Kaj če funkcijo preoblikujemo tako, da sprejme ime in jo potem kličemo iz neke druge funkcije? Omenjena ideja je predstavljena spodaj:
Sub Proc2(ime As String) Dim a As New objSciti a.init ime End Sub Sub TestProc2() Dim i For i = 1 To 20 Proc2 "spr"; i Next End Sub
Če izvedemo testno proceduro ‘TestProc2‘, dobimo sledeč rezultat
NOV POSTAVIM spr1 BRIŠEM spr1 NOV POSTAVIM spr2 BRIŠEM spr2 … in tako dalje … NOV POSTAVIM spr20 BRIŠEM spr20
To je torej lep dokaz, da se objekt ob zaključku funkcije avtomatično uniči in nam za to ni potrebno skrbeti. Iz rezultata je namreč vidno, da se funkcija izvede 20x in vsakič kliče proceduro, ki objekt ustvari in ga tudi uniči. In to preprosto dejstvo nam lahko reši neprespane noči ob iskanju hrošča 🙂
Konkreten primer uporabe vam bom prikazal naslednjič, za danes pa podajam samo še dve zelo pomembni opozorili.
Opozorilo1
V kolikor ste navajeni klasičnih programskih jezikov, kot sta recimo C in C++ lahko pridete na idejo, da vso pomembno programsko kodo postavite v konstruktor in ustrezno čiščenje v destruktor…
TODA, če v VBA-ju ne uporabite vsaj ene javne funkcije/ metede/ lastnosti objekta, ga VBA izvajalno okolje ne bo naredilo. Torej VBA takšnega objekta sploh nikoli ne bo ustvaril.
Če prejšnjo funkcijo preoblikujete takole:
Sub Proc2(ime As String) Dim a As New objSciti ' objekta nikoli ne uporabimo ' zato ga VBA sploh ne bo ustvaril! End Sub
Program ne bo izpisal ničesar!
Opozorilo2
V kolikor ste navajeni klasičnih programskih jezikov, kot sta recimo C in C++ lahko pričakujete, da bo VBA uničil objekt ob koncu programskega bloka. A to v primeeru VBA-ja ne drži. VBA uničuje objekte samo na koncu funkcij /procedur.
Primer je lepo viden, če v testni proceduri ne kličemo procedure, temveč objekt direktno ustvarimo:
Sub TestProc3() Dim i For i = 1 To 20 ' VBA bo objekt ustvaril samo 1x ! Dim a As New objSciti ' lastnosti bo spreminjal ISTEMU objektu a.init "spr"; i Next ' objekt a ne bo uničen tukaj ' temveč bo uničen šele tukaj End Sub
Sedaj pa je izpis povsem drugačen:
NOV POSTAVIM spr1 POSTAVIM spr2 … in tako dalje … POSTAVIM spr20 BRIŠEM spr20
Na primeru je lepo vidno, da VBA ustvari en sam objekt. Bodite pozorni na to!