× Aktuálně z oboru

Programátoři po celém světě dnes slaví Den programátorů [ clanek/2018091300-programatori-po-celem-svete-dnes-slavi-den-programatoru/ ]
Celá zprávička [ clanek/2018091300-programatori-po-celem-svete-dnes-slavi-den-programatoru/ ]

VB.NET - díl 6.

[ http://programujte.com/profil/14993-jakub-ledl/ ]Google [ ?rel=author ]       [ http://programujte.com/profil/118-zdenek-lehocky/ ]Google [ ?rel=author ]       23. 9. 2009       25 530×

V dnešním díle budeme pokračovat v OOP – probereme dědičnost, datový typ Object a generiku.

V dalším díle kurzu budeme pokračovat v tom, co jsme začali minule – OOP, ale již na trošku pokročilejším stupni.

Dědičnost

Co je to dědičnost jako taková, ví snad každý. V programování ovšem dědičnost není jako mezi lidmi, že geneticky zdědíte barvu vlasů po dědečkovi. Dědičnost funguje mezi třídami a znamená, že jedna třída podědí od druhé její metody, proměnné a vlastnosti. Jako vždy si pro lepší pochopení uvedeme konkrétní příklad:

Programujete aplikaci simulující chod letiště. Základním objektem, který využijeme, je Letadlo:

Class Airplane
    Public Sub StartEngines()
        'Kód pro spuštění motorů
    End Sub

    Public Sub TakeOff()
        'Kód pro vzlet
    End Sub

    Public Sub Land()
        'Kód pro přistání
    End Sub

    Public Sub Ascend(ByVal dif As Integer)
        'Kód pro vystoupání do vyšší letové hladiny
    End Sub

    Public Sub Descend(ByVal dif As Integer)
        'Kód pro sestoupení do nižší letové hladiny
    End Sub

    Public Sub ChangeDirection(ByVal degrees As Integer)
        'Kód pro změnu směru
    End Sub
End Class

Každé letadlo umí základní věci jako vzlétnout, přístát, změnit směr, klesat, stoupat… Ale jsou věci, které umí pouze vojenská letadla, jako vysadit parašutisty, shodit bombu, a jsou vlastnosti, které mají pouze dopravní letadla, jako počet cestujících v bussiness třídě, v první třídě… Tyto věci naše třída Letadlo neumí, a kdybychom je do ní měli všechny napsat, byl by z toho strašlivý mix luxusního dopraváku, práškovacího letadla a jaderného bombardéru. Místo toho použijeme dědičnost. Třída Dopravní Letadlo bude dědit z třídy Letadlo, čímž získá všechny metody pro vzlet, přístání apod. a zároveň jí budeme moci nadefinovat vlastnosti specifické pro dopravní letadlo:

Class AirLiner
    Inherits Airplane
    'Pro označení dědičnosti slouží konstrukce Inherits [typ, ze kterého třída dědí]
    Private _passengersInBussinessClass As Integer = 0, _passengersInFirstClass As Integer = 0

    Public Property PassengersInBussinessClass() As Integer
        Get
            Return _passengersInBussinessClass
        End Get
        Set(ByVal value As Integer)
            _passengersInBussinessClass = value
        End Set
    End Property

    Public Property PassengersInFirstClass() As Integer
        Get
            Return _passengersInFirstClass
        End Get
        Set(ByVal value As Integer)
            _passengersInFirstClass = value
        End Set
    End Property
End Class

...

Sub Main()
    Dim jumboJet As New AirLiner
    jumboJet.PassengersInBussinessClass = 366
    jumboJet.PassengersInFirstClass = 452
    'Jelikož třída AirLiner dědí od třídy AirPlane,
    'můžeme bez obav volat metody definované v
    'základní třídě.
    jumboJet.TakeOff()
End Sub

To funguje naprosto dokonale pro letadla, ale co kdybychom chtěli přidat do „letového parku“ další třídu, třeba vrtulník? Vrtulník má dost společného s letadlem, proto ho můžeme odvodit od třídy Letadlo, ale startuje a přistává úplně jinak. Jak tedy můžeme předefinovat metody pro vzlet a přistání? Použijeme klíčové slovo Overrides, se kterým jsme se setkali už v minulé lekci:

Class Helicopter
    Inherits Airplane

    'Klíčové slovo Overrides značí, že daná metoda/funkce/vlastnost
    '"přepíše chování stejně pojmenované metody v základní třídě.
    'Pozor! Přepisující metoda musí musí mít stejné parametry a 
    'návratovou hodnotu jako metoda přepisovaná!
    Public Overrides Sub TakeOff()
        '...
    End Sub

    Public Overrides Sub Land()
        '...
    End Sub
End Class

Ovšem pozor! Tento příklad by nešlo zkompilovat! Abychom umožnili přepsání metody/funkce/vlastnosti, musíme je definovat jako „přepisovatelnou“ – Overridable. Upravíme tudíž definici třídy letadlo takto:

Class Airplane
    Public Sub StartEngines()
        'Kód pro spuštění motorů
    End Sub

    Public Overridable Sub TakeOff()
        'Kód pro vzlet
    End Sub

    Public Overridable Sub Land()
        'Kód pro přistání
    End Sub

    ...

End Class

Členy deklarované jako Overridable fungují takto: Zavolám metodu z odvozené třídy. Pokud existuje její přepsaná (Overrides) varianta, zavolá se ta. Pokud žádná přepsaná varianta neexistuje, zavolá se původní metoda ze základní třídy.

Pozn.: V termínech OOP se těmto členům říká virtuální.

Někdy může nastat situace, že budete chtít zavolat z přepisující metody přepisovatelnou metodu v základní třídě. K tomu slouží klíčové slovo MyBase, které slouží jako alias pro třídu, ze které konkrétní třída dědí:

Public Class Foo
    Protected Overridable Sub Baz()
        '...
    End Sub
End Class

Class Bar
    Inherits Foo

    Protected Overrides Sub Baz()
        '...
        MyBase.Baz()
        'Samozřejmě, základní metodu nemusíte volat pouze
        'na konci přepisující metody, ale kdekoli v jejím těle.
    End Sub

End Class

Jedna ze situací, které při vašem programování může vzniknout, je, že chcete napsat třídu, ze které nebude možné dědit. Jak na to? VB.NET nám nabízí další klíčové slovo: NotInheritable.

NotInheritable Class Foo

End Class

Class Bar
    Inherits Foo
    'Chyba! Třída Foo je NotInheritable!

End Clas

Ve VB.NET je ještě jedno dosti podobné klíčové slovo – NotOverridable. Slouží k označení metody, kterou nebude možné přepsat ve třídě, která dědí od konkrétní třídy, ovšem pozor! Jako NotOverridable smí být deklarována pouze metoda, která už je přepisující (Overrides):

Class Foo
    Public Overridable Sub Baz()

    End Sub
End Class

Class Bar
    Inherits Foo

    Public NotOverridable Overrides Sub Baz()

    End Sub
End Class

Class FooBar
    Inherits Bar

    'Chyba! Metoda Baz třídy Bar je NotOverridable!
    Public Overrides Sub Baz()

    End Sub
End Class

Datový typ Object

Možná jste si už všimli, že pokud vytvoříte novou třídu, která z žádné třídy nedědí, tak přesto se po napsání klíčového slova Overrides zobrazí nějaké metody. Jsou to metody Equals, GetHashCode a ToString.

Ptáte se, odkud je naše třída vzala, ačkoli od ničeho nedědí? Pochází z třídy System.Object, která je tak důležitá, že má pro ni VB.NET speciální klíčové slovo Object:

Dim o As Object

Ptáte se, čím je tato třída speciální? Od třídy System.Object totiž automaticky dědí všechny třídy v .NET frameworku. To znamená, že datový typ Object lze použít jako zástupce kteréhokoli datového typu:

    Sub Main()
        Dim o As Object
        o = 3.14
        Console.WriteLine(o)
        o = "Hello World"
        Console.WriteLine(o)
    End Sub

Výše uvedený příklad je naprosto legální, funkční a zkompilovatelný, jelikož v typu Object lze uschovat instanci jakékoli třídy. Při přiřazování do datového typu Object dochází k tzv. boxingu – proměnná, třeba typu Integer, se zabalí a uloží do datového typu Object.

Unboxing a kontrola skutečného typu

Unboxing je proces přetypování (změny datového typu proměnné). Pro tento účel má VB.NET funkci (operátor) CType:

Dim o As Object = 3 'boxing
Dim i As Integer = CType(o, Integer) 'unboxing

Pukud chcete provést převod na některý z běžných datových typů, VB.NET opět nabízí speciální funkce:

  • CBool pro Boolean
  • CByte pro Byte
  • CChar pro Char
  • CDate pro Date
  • CDbl pro Double
  • CDec pro Decimal
  • CLng pro Long
  • CShort pro Short
  • CSng pro Single
  • CStr pro String

Pokud chceme otestovat opravdový datový typ proměnné Object, musíme použít operátor TypeOf:

Dim o As Object = 3 'boxing

If TypeOf o Is Integer Then
  '...
End If

Testování je velice důležité, představte si následující situaci: Do proměnné o typu Object uložíte celé číslo a pak se pokusíte zavolat CDate(o). Jelikož VB.NET neví, jak má převést celé číslo na datum, tak program skončí vyjímkou typu InvalidCastException – neplatný převod. TypeOf slouží k zjištění toho, zda je bezpečné provést přetypování.

Generické typy

Zavedení generických typů znamenalo velký průlom pro jazyk VB.NET. Umožňuje totiž přesně specifikovat, s jakým datovým typem chceme v třídě pracovat. Ukázka:

'Stará třída HashTable sloužila k definování párů klíč/hodnota. Před zavedením generických typů 
'byl jak klíč, tak hodnota typu Object a bylo nutné provádět přetypování.

Dim h As New Hashtable
h.Add("first", 6)
Dim o As Integer = CInt(h("first"))
'Zkuste napsat toto do editoru a uvidíte, že HashTable všude používá Object.

'Nová verze třídy HashTable jménem Dictionary ovšem umí pracovat s generickými typy a umožňuje definovat
'přesný datový typ klíče i hodnoty:

Dim d As New Dictionary(Of String, Integer) 'klíčové slovo Of specifikuje datové typy
d.Add("first", 6) 'Intellisense nám rovnou napoví, že klíč má být typu String a hodnota Integer, ne Object a Object
Console.WriteLine(d("first")) 'A tady dostaneme rovnou Integer, nikoli Object

Generické mohou být třídy (pak bude konstrukce Of [typ] zapsána u názvu třídy. Generické mohou být ale samotné metody; zapišme si metodu, která přehodí hodnoty dvou proměnných hodnotového typu:

Sub Swap(Of TSwap)(ByRef first As TSwap, ByRef second As TSwap)
    Dim temp As TSwap = first
    first = second
    second = temp
End Sub

Sub Main()
    Dim a As Integer = 8, b As Integer = 6
    Swap(Of Integer)(a, b) 'Při psaní tohoto volání pozorně sledujte Intellisense
    Console.WriteLine(a)
    Console.WriteLine(b)
End Sub

V příštím díle budeme pokračovat v OOP a podíváme se na některé skutečně pokročilé techniky. Jakmile dobereme všechnu teorii, podíváme se na „praktičtější ukázky“ – důležité a užitečné třídy v .NET Frameworku, kolekce apod.


Článek stažen z webu Programujte.com [ http://programujte.com/clanek/2009090201-vb-net-dil-6/ ].