Visual Basic zblízka
Dědičnost a rozhraní
Dnes si povíme něco o dědičnosti a rozhraních. Visual Basic neobsahuje přímo podporovanou dědičnost. Bez této možnosti se sice dá v objektovém programování obejít, ale znemožní nám to elegantní znovupoužití již existující funkčnosti. Samozřejmě toto lze provést i jinými způsoby. První, s pomocí kterého můžeme předstírat dědičnost, funguje tak, že uvnitř třídy vytvoříme instanci děděného objektu a vytvoříme metody, vlastnosti a události se stejnými jmény v odvozeném objektu, přičemž v kódu přesměrujeme volání metod na vložený objekt. Když pomineme pracnost, je velkou nevýhodou tohoto způsobu, že při něm VB nebude mít nejmenší ponětí o tom, že výsledná třída je odvozená od jiné a tím pádem dosáhneme polymorfizmu pouze na úrovni typu Object .
Méně pracným způsobem, jakým lze znovupoužít existující funkčnost je agregace. Ta spočívá v tom, že s pomocí vlastnosti vyvedeme odkaz na objekt, jehož funkčnost chceme využít, ven z vytvářené třídy. Problémem ovšem je, že VB agregaci nepodporuje. Vy sice zveřejníte objekt s pomocí vlastnosti, ale při jeho používání mohou nastat nekonsistentní situace.
Vytváří-li nějaký objekt uvnitř sebe objekt jiný, je logické, že životnost vnitřního objektu je bezprostředně závislá na objektu vnějším. Zanikne-li objekt vnější zaniknou i všechny vnitřní. Toto ovšem VB nezvládne. Jestliže vytvoříte takovýto objekt a s pomocí vlastnosti získáte odkaz na vnitřní objekt a poté odstraníte všechny odkazy na objekt vnější, vyvoláte tím jeho destrukci. Ale jelikož existuje odkaz na vnitřní objekt, tak ten stále existuje, ačkoli objekt, který ho vytvořil a jehož neoddělitelnou součástí by měl být, je již v křemíkovém nebi. Ptáte se proč je tomu tak? Je to prosté, podle pravidel, která jsme si uvedli v prvním díle vše funguje tak jak má. Ovšem tato pravidla pro uvedený způsob nejsou vhodná. Aby uvedený způsob fungoval, musí pro objekt vnější a všechny vnitřní existovat pouze jedno počítadlo, takže dokud existuje odkaz na objekt vnější nebo na libovolný objekt vnitřní, neproběhne destrukce ani jednoho z nich.
Jednou ze zajímavých možností, které VB nabízí je možnost implementovat objektu různá rozhraní. Co si pod tím můžete představit? Rozhraní je množina metod a vlastností, které určují způsob komunikace s objektem. Každý objekt jich může mít nepočítaně a závisí jen na vás, které se následně rozhodnete používat, ať už implicitní nebo jiné. Může existovat několik odkazů na objekt, přičemž každé pracuje s jiným rozhraním ale, se stejnou instancí objektu.
Ve VB se s rozhraními pracuje následovně. Vytvoříte abstraktní (obsahující pouze deklaraci metod) třídu, i když nemusí být nutně abstraktní, jejíž metody a vlastnosti budou představovat jednotlivé části rozhraní. Vložte dvě třídy s názvy ICzech a IEnglish a vložte do nich následující kód, který bude představovat jednotlivé členy rozhraní. V těchto třídách nemusí být žádný kód.
'abstraktní třída rozhraní ICzech
Public Property Get MojeVlastnost() As String
End Property
Public Property Let MojeVlastnost(Value As String)
End Property
Public Function MojeMetoda() As String
End Function
Public Function MojeMetodaEN() As String
End Function
'abstraktní třída rozhraní IEnglish
Public Property Get MyProperty() As String
End Property
Public Property Let MyProperty(Value As String)
End Property
Public Function MyMethod() As String
End Function
Public Function MyMethodCZ() As String
End Function
Nyní máme vytvořena rozhraní, tak se pustíme do jejich implementace do třídy, která je bude využívat. Vložte novou třídu a nazvěte ji MyClass . Pomocí klíčového slova Implements třídě zdělíme, že bude implementovat naše rozhraní. Jednotlivé členy rozhraní se budou do třídy vkládat ve formě názevrozhraní_názevčlena. Do takto vytvořených metod a vlastností pak vložíme samotný kód. Ten je velice jednoduchý. Nastavíte do vlastnosti řetězec a metodami pak získáte oznámení, co se ve vlastnsti právě nachází.
Implements ICzech
Implements IEnglish
Private mCZVar As String
Private mENVar As String
Private Function ICzech_MojeMetoda() As String
ICzech_MojeMetoda = "Toto je tvůj řetězec: " & mCZVar
End Function
Private Function ICzech_MojeMetodaEN() As String
ICzech_MojeMetodaEN = "Toto je tvůj anglický řetězec: " & mENVar
End Function
Private Property Let ICzech_MojeVlastnost(Value As String)
mCZVar = Value
End Property
Private Property Get ICzech_MojeVlastnost() As String
ICzech_MojeVlastnost = mCZVar
End Property
Private Function IEnglish_MyMethod() As String
IEnglish_MyMethod = "This is your string: " & mENVar
End Function
Private Function IEnglish_MyMethodCZ() As String
IEnglish_MyMethodCZ = "This is your czech string: " & mCZVar
End Function
Private Property Let IEnglish_MyProperty(Value As String)
mENVar = Value
End Property
Private Property Get IEnglish_MyProperty() As String
IEnglish_MyProperty = mENVar
End Property
A nyní si vytvoříme aplikaci, na které si budeme ilustrovat použití našich rozhraní a třídy. Vložte na formulář tři tlačítka a do vlastnsti Caption , ve stejném pořadí v jakém jste jej vytvořili, vložte popisky „CZ“, „EN“ a „Test“. Poté vložte dva TextBoxy, ze kterých bude nastavovat vlastnosti.
Uvedeme si první příklad. Vněm do proměnné typu ICzech přiřadíte novou instanci objektu MyClass . Ta pak bude používat vlastní funčnost, ale pouze rozhraní vytvořené třídou ICzech .
Private Sub Command1_Click()
Dim cz As ICzech
Set cz = New MyClass
cz.MojeVlastnost = Text1.Text
MsgBox cz.MojeMetoda, vbOKOnly, "cz.MojeMetoda"
End Sub
Druhý příklad bude provádět to samé, ale stím rozdílem, že bude využívat rozhraní IEnglish .
Private Sub Command2_Click()
Dim en As IEnglish
Set en = New MyClass
en.MyProperty = Text2.Text
MsgBox en.MyMethod, vbOKOnly, "en.MyMethod"
End Sub
V posledním příkladu si ilustrujeme, že když nadeklarujete proměnnou určitého typu (rozhraní), bude vždy používat stále stejné rozhraní bez ohledu na to, z jakého typu (rozhraní) je mu odkaz na objekt přiřazen. Navíc je ilustrováno, že implementovaná rozhraní mohou používat stejné prostředky, čili prostředky, které má třída, jež je implementuje.
Private Sub Command3_Click()
Dim cz As ICzech
Dim en As IEnglish
Dim mc As MyClass
'vytvoří instanci MyClass
Set mc = New MyClass
'Přiřadí se instance MyClass do proměnné,
'která se odkazuje na české rozhraní
Set cz = mc
'Přiřadí se instance MyClass do proměnné,
'která se odkazuje na anglické rozhraní
Set en = mc
'Všechny proměnné (mc, en, cz) se odkazují
'na stejnou instanci, ale na rozdílná rozhraní
en.MyProperty = Text2.Text
cz.MojeVlastnost = Text1.Text
'České rozhraní vypíše český řetězec
MsgBox cz.MojeMetoda, vbOKOnly, "cz.MojeMetoda"
'České rozhraní vypíše anglický řetězec
MsgBox cz.MojeMetodaEN, vbOKOnly, "cz.MojeMetodaEN"
'Anglické rozhraní vypíše anglický řetězec
MsgBox en.MyMethod, vbOKOnly, "en.MyProperty"
'Anglické rozhraní vypíše český řetězec
MsgBox en.MyMethodCZ, vbOKOnly, "en.MyPropertyCZ"
'přiřadí se okaz na objekt z jiného rozhraní,
'ale stále se bude pracovat s anglickým
Set en = cz
'Anglické rozhraní opět vypíše anglický řetězec
MsgBox en.MyMethod, vbOKOnly, "en.MyProperty"
'Anglické rozhraní opět vypíše český řetězec
MsgBox en.MyMethodCZ, vbOKOnly, "en.MyPropertyCZ"
End Sub
Různá rozhraní vám umožní buď oddělit jednotlivé části funkčnosti objektu nebo pracovat s objektem různými způsoby. Uvedený příklad můžete nalézt zde.
|