Integrované prostředí rubriky Visual Basic |
|||||||
|
Programátorská laboratoř |
||||||
Prostor pro experimentování |
|||||||
Časová náročnost (min): 85 |
Začátečník |
Pokročilý |
Profesionál |
||||
|
|
|
|||||
|
Použitý operační systém : Hlavní vývojový
nástroj : Další vývojový software : Jiný software : |
Windows 2000 SP3 Visual Basic .NET 2002 Žádný Žádný |
|||||
|
|
|
||
|
|
||
|
|
||
|
|
Tvorba abstraktní třídy
Jednou z významných vlastností, které spadají do oblasti objektově orientovaného programování ve Visual Basicu .NET, je tvorba abstraktních tříd. Hned na začátek si ovšem musíme říci, že psaní abstraktních tříd nepatří zrovna mezi běžné úkoly programátora ve VB .NET. Na druhou stranu, pochopení principu, na němž spočívají základy tematiky abstraktních tříd, vás katapultuje do vyšších úrovní hry, které se říká profesionální programování.
Abstraktní třídy jsou třídy, které nejsou určeny pro přímou tvorbou objektů jistého typu. Znamená to, že abstraktní třída nemůže sloužit jako „továrna na objekty“. Ve skutečnosti zastává abstraktní třída pozici bázové třídy, ze které mohou jiné třídy dědit veškerou funkcionalitu. Ovšem výraz, že jiné třídy můžou dědit z abstraktní třídy, je poněkud slabý. Skutečnost je taková, že jiné třídy musí dědit z abstraktní třídy. Tato vskutku fundamentální vlastnost abstraktní třídy je umocněna použitím klíčového slova MustInherit v deklaraci abstraktní třídy. I když abstraktní třída může obsahovat definice členských funkcí a procedur, obvykle jsou v abstraktní třídy uvedeny pouze deklarace těchto entit. Když vycházíme ze skutečnosti, že abstraktní třídou nelze přímo použít pro tvorbu objektů, je toto chování pochopitelné. V praxi se zvyčejně postupuje tak, že do abstraktní třídy se umístí pouze deklarace členů třídy, a konkrétní implementace těchto členů je následně ponechána na odvozené třídě. Jestliže již netrpělivě čekáte na ukázku abstraktní třídy, nebudu vás dále napínat. V následující případové studii si ukážeme, jak zhotovit jednoduchou abstraktní třídu. Postupujte takto:
Public MustInherit Class A
Public
MustOverride Sub
VytvořitFormulář()
End Class
Jak jsme si již řekli, v deklaraci abstraktní třídy se musí nacházet klíčové slovo MustInherit, které indikuje, že tato třída je určena pouze pro tvorbu z ní odvozených podtříd. V těle abstraktní třídy se nachází deklarace jednoho abstraktního členu této třídy. Přesněji jde o deklaraci procedury Sub s názvem VytvořitFormulář. Jak můžete vidět, v deklaraci členské procedury se nachází klíčové slovo MustOverride, které říká, že ještě předtím, než bude tato procedura použita, musí být překryta v kódu odvozené třídy. Při deklaraci členské procedury v abstraktní třídě je zapotřebí určit jenom indikátor přístupu (Public), klíčové slovo MustOverride a jméno procedury (VytvořitFormulář), které je následováno závorkami (v tomto případě prázdnými). Pokud byste chtěli, nic vám nebrání v tom, abyste přidali vlastní parametry s příslušnými datovými typy a návratovou hodnotu (v případě deklarace funkce).
|
Proceduru typu Sub můžete snadno „předělat“ na funkci nahrazení
klíčového slova Sub v deklaraci klíčovým slovem Function. Pokud
se rozhodnete implementovat funkci, nezapomeňte také řádně specifikovat její návratovou
hodnotu. |
Public Class B
Inherits
A
Public
Overrides Sub
VytvořitFormulář()
Dim
frm As New Form()
With
frm
.Text = "Formulář č. 1"
.Show()
End
With
End
Sub
End Class
Skutečnost, že třída B je odvozená do abstraktní třídy A, demonstruje příkaz Inherits. Protože abstraktní třída nabízí jenom deklaraci členské procedury, leží povinnost její implementace na bedrech odvozené třídy. Odvozená třída B se tedy této úlohy musí chtě-nechtě zhostit, a proto překryje proceduru z abstraktní třídy A. Aby bylo na první pohled jasné, že procedura překrývá proceduru z abstraktní třídy, je do deklarace překryté procedury vloženo klíčové slovo Overrides. V těle překryté procedury je vytvořena nová instance třídy Form, které je přiřazen text, jenž se bude zobrazovat v titulkovém pruhu okna instance a tato instance je posléze zobrazena.
|
Možná se divíte, jak může být vytvořen objekt třídy Form, když ani jedna ze tříd nedědí z třídy System.Windows.Forms.Form.
Fígl spočívá v tom, že vaše odvozená třída ví o třídě Form, a
také ví, kde se táto třída nachází. Řekne jí to totiž Visual Basic .NET,
protože odkaz na vzpomínanou třídu se nachází v sekci odkazů (References)
v okně Solution Explorer. |
Dim
ObjektováProměnná As New B()
ObjektováProměnná.VytvořitFormulář()
Jestliže spustíte aplikaci a klepněte na tlačítko, zobrazí se nový formulář s předem určeným textem v titulkovém pruhu.
Tvorba a implementace
rozhraní
Ve světě, v němž vládnou objekty, je velmi důležité, aby se tyto objekty dokázali mezi sebou domluvit. Aby ovšem bylo možné uskutečnit vůbec nějakou konverzaci mezi objekty, musí nejprve existovat jistý protokol, neboli rozhraní, které umožní přistupovat k metodám a vlastnostem objektů. Pod pojmem rozhraní si tedy můžete představit jistou smlouvu, nebo dohodu, která říká, jak bude uskutečňován komunikační proces mezi objekty. Jestliže jste používali nižší verze Visual Basicu, mohli jste rozhraní používat, ovšem jejich tvorba byla svěřena jiným programovacím jazykům (především Visual C++). S příchodem .NET verze jazyka Visual Basic se situace radikálně změnila, a proto se i my můžeme těšit na programovaní rozhraní.
Z technického hlediska je rozhraní ryzí informační protokol, který má jisté charakteristiky společné s tvorbou abstraktní třídy. Rozhraní se deklaruje příkazem Interface a v těle tohoto příkazu se uvádějí prototypy potřebných procedur, funkcí, vlastností a událostí, které má rozhraní podporovat. Prototypem se rozumí pouze specifikace členu rozhraní, jeho jména, signatury a návratové hodnoty (jestliže je zapotřebí). Je velmi důležité si uvědomit, že definice rozhraní pozůstává jenom z uvedených prototypů členů. Veškerá implementace členů rozhraní je (opět podobně jako u abstraktních tříd) přenesena do třídy, která bude uvedené rozhraní implementovat. Zjednodušeně by se dalo říct, že rozhraní definuje pouze to, „co se má udělat“ a implementační třída zase nařizuje „jak se to má udělat“.
Aby ovšem nezůstalo jen u teorie, pokusíme se sestavit rozhraní, poté jej implementovat a využít ve třídě. Zde jsou všechny potřebné instrukce:
Public Interface
IRozhraní
Sub
SpustitProgram(ByVal JménoProgramu As String)
ReadOnly
Property ZjistitIDProcesu()
End Interface
Rozhraní je definováno mezi příkazy Interface a End Interface. Příkazu Interface předchází určení modifikátoru přístupu (Public). Rozhraní je v našem případě veřejné, je tedy přístupné v rámci celého projektu. Za příkazem Interface následuje jméno rozhraní a podle konvence začíná toto jméno na písmeno „I“. V těle rozhraní se nacházejí deklarace členů rozhraní, které mají stejnou úroveň přístupu jako celé rozhraní (Public). Můžete zde vidět jednu Sub proceduru s názvem SpustitProgram, která pracuje s jedním parametrem typu String s názvem JménoProgramu. Dalším členem je vlastnost ZjistitIDProcesu, která je určena jenom pro čtení, což indikuje použití klíčového slova ReadOnly.
Public Class C
Implements
IRozhraní
Dim
m_Proces_ID As Integer
Public
Sub SpustitProgram(ByVal
JménoProgramu As String)
_
Implements
IRozhraní.SpustitProgram
Dim
proc As New
Process()
With
proc
.StartInfo.FileName
= JménoProgramu
.Start()
End
With
m_Proces_ID
= proc.Id
End
Sub
Public
ReadOnly Property
ZjistitIDProcesu() _
Implements
IRozhraní.ZjistitIDProcesu
Get
Return
m_Proces_ID
End
Get
End
Property
End Class
Zde vidíte výpis kódu pro třídu C. Ihned za deklaračním příkazem třídy se nachází příkaz Implements s názvem rozhraní pro implementaci. Příkaz Implements determinuje, že třída C bude podporovat rozhraní IRozhraní a je nutné, aby třída definovala všechny členy rozhraní. To třída C také na následujících řádcích dělá. Nejdřív je plně implementována Sub procedura SpustitProgram. Všimněte si prosím, že za signaturou procedury SpustitProgram je opět uveden příkaz Implements, za kterým je uveden člen rozhraní, který je prostřednictvím procedury implementován. V rámci procedury je vytvořena instance třídy Process s názvem proc. Jméno programu, jenž se bude spouštět je uloženo do vlastnosti Filename. Běh kódu pokračuje zavoláním metody Start, která zabezpečí spuštění specifikovaného souboru.
Implementována je i vlastnost ZjistitIDProcesu, která vrací identifikační číslo spuštěného procesu. Opět si všimněte, že je potřebné zapsat příkaz Implements za jméno vlastnosti a určit odpovídající protějšek z definice rozhraní.
Dim x As New C()
x.SpustitProgram("Notepad.exe")
Me.Text = "ID procesu: " & x.ZjistitIDProcesu
Tento kód vytváří objektovou proměnnou x, která obsahuje referenci na instanci třídy C. Ve druhém kroku je zavolána metoda SpustitProgram, které je předán název programu, jenž se má spustit. Poslední příkaz zobrazuje identifikační kód právě spuštěného programu (procesu) v titulkovém pruhu testovací aplikace.
Překrytí metody v odvozené třídě
V tomto tipu si ukážeme, jak překrýt metodu bázové třídy v odvozené třídě. Začneme však zvolna a vysvětlíme si, co se pod pojmem překrývání metod ve skutečnosti rozumí. Proces překrývání metod není ve světě programování nijak nový, ostatně mnohé jazyky, například C++, jej používají již nějaký ten pátek. Hlavní myšlenka je takováto: Pomocí překrývání metod můžete jednoduše nahradit metodu bázové třídy svou vlastní metodou, která může mít zcela jinou implementaci. Jak je jistě patrné, proces překrývání metod je velice úzce spjat s procesem dědění. Představte si následující příklad: Máte dvě třídy, jednu bázovou a druhou odvozenou z bázové třídy. S funkcionalitou bázové třídy jste vcelku spokojeni, ovšem přáli byste si, aby několik metod bázové třídy disponovalo novější stavbou programového kódu, a zajišťovalo lepší funkcionalitu. Pokud se někdy dostanete do podobné situace, určitě přivítáte pomocnou ruku, kterou vám mechanizmus překrývání metod může nabídnout. Výsledkem bude jednoduše překrytí metody bázové třídy (programový kód překryté metody bude zcela jiný a bude tak poskytovat modifikovanou funkcionalitu).
|
Při překrývání metody ovšem nesmíte zapomenout na skutečnost, že nová
implementace metody musí mít stejný modifikátor přístupu, název a rovněž tak
i stejnou signaturu jako metoda, kterou se chystáte překrýt. |
Překrývání metody v odvozené třídě si budeme demonstrovat na následující programové ukázce.
Public Class BázováTřída
Public
Overridable Sub ZobrazitČas()
MessageBox.Show("Právě teď je " & _
DateTime.Now.TimeOfDay.Hours
& _
" hodin.")
End
Sub
End Class
Public Class OdvozenáTřída
Inherits
BázováTřída
Public
Overrides Sub
ZobrazitČas()
Form.ActiveForm.Text
= "Právě teď je "
& _
DateTime.Now.TimeOfDay.Hours
& " hodin."
End
Sub
End Class
Předmětem našeho zájmu je procedura ZobrazitČas. Tato procedura je v bázové třídě definována s klíčovým slovem Overridable, které z procedury dělá vhodného kandidáta pro pozdější překrytí. Mimochodem, metoda ZobrazitČas v bázové třídě je zodpovědná za zobrazení dialogového okna s počtem uplynulých hodin dne.
Třída s názvem OdvozenáTřída dědí svou funkcionalitu z bázové třídy. I v této třídě se nachází kód s metodou ZobrazitČas, ovšem jak si můžete všimnout, tato metoda:
· je deklarována s použitím klíčového slova Overrides,
· provádí jinou činnost nežli její předchůdkyně v bázové třídě (zobrazuje počet hodin v titulkovém pruhu aktivního formuláře),
· má stejný modifikátor přístupu (Public), název (ZobrazitČas) i signaturu.
Můžeme prohlásit, že metoda ZobrazitČas v odvozené třídě překrývá metodu ZobrazitČas v bázové třídě.
Dim obj As New OdvozenáTřída()
obj.ZobrazitČas()
Výsledek můžete vidět na obr. 1.
Obr. 1 – Zavolání překryté metody
z odvozené třídy
Rotace rastrového obrázku
Programátoři grafických aplikací se zcela určitě nezaobejdou bez techniky rotování rastrových obrázků. Dobrou zprávou je, že platforma .NET poskytuje množství tříd, které vám mohou při programování různých grafických efektů v mnohém pomoci. My se nyní podíváme na to, jak rotovat jednoduchým rastrovým obrázkem, jenž je uložen ve formátu GIF. Budeme postupovat takto:
With
PictureBox1
.BorderStyle = BorderStyle.FixedSingle
.SizeMode = PictureBoxSizeMode.CenterImage
.Image = Image.FromFile("D:\obr1.gif")
End With
Aby měl ovládací prvek PictureBox1 vizuálně ohraničenou plochu, upravíme jeho vlastnost BorderStyle na hodnotu FixedSingle. Dále je nastavena vlastnost SizeMode na hodnotu CenterImage, což znamená, že obrázek, jenž bude vykreslen na ploše tohoto ovládacího prvku, bude okamžitě vycentrován horizontálně i vertikálně. V další etapě je do vlastnosti Image ovládacího prvku PictureBox1 umístěna reference na objekt Image, který je tvořen rastrovým obrázkem načteným z předem připraveného grafického souboru.
Dim g As Image = PictureBox1.Image
g.RotateFlip(RotateFlipType.Rotate270FlipNone)
PictureBox1.Refresh()
Zde jsou realizovány tyto úkony:
·
je
vytvořena objektová proměnná g, do které je uložena
reference na objekt s rastrovým obrázkem (tato reference je získána z vlastnosti
Image ovládacího prvku PictureBox1),
· je použita metoda RotateFlip, která provede rotaci obrázku o 270 stupňů,
· je překreslena plocha ovládacího prvku PictureBox1 použitím metody Refresh.
Načtený obrázek a jeho modifikovanou verzi můžete vidět na obr. 2.
Obr. 2 – Rotace rastrového
obrázku
Ján Hanák