× Aktuálně z oboru

SHIELD Experience Upgrade 7 – méně hledání a více zábavy [ clanek/2018052902-shield-experience-upgrade-7-mene-hledani-a-vice-zabavy/ ]
Celá zprávička [ clanek/2018052902-shield-experience-upgrade-7-mene-hledani-a-vice-zabavy/ ]

VB.NET - díl 5.

[ http://programujte.com/profil/14993-jakub-ledl/ ]Google [ ?rel=author ]       [ http://programujte.com/profil/14523-martin-simecek/ ]Google [ ?rel=author ]       2. 9. 2009       23 977×

V tomto díle se podíváme na základy objektově orientovaného programování (OOP).

V našem seriálu o jazyce VB.NET jsme toho již probrali poměrně dost:

  • proměnné a funkce,
  • podmínky, rozhodovací struktury,
  • cykly,
  • pole,
  • ošetřování výjimek.

Tyto prvky tvoří dohromady něco, čemu říkáme procedurální programování. Objektové programování je logicky další krok, o který musíme popojít.

Co to jsou ty objekty?

Představte si, že programujeme aplikaci, ve které chceme popsat nějaký předmět; třeba auto. V jazyce, který nepodporuje objektový model (např. jazyk C) můžeme auto popsat sérií proměnných a funkcí. To sice může vyhovovat, ale při větších projektech se tento popis může stát rychle nepřehledným. V OOP ale můžeme popsat auto jako jeden objekt, kterému nadefinujeme potřebné metody a funkce (Jeď, Zastav, ZměňRychlost) a data (rychlost, barva, typAuta). Velmi to pomáhá přehlednosti projektů, na kterých pracujeme.

Deklarace třídy

Třídu deklarujeme klíčovým slovem Class:

Public Class Car

End Class

Třída může obsahovat metody, proměnné a vlastnosti (properties):

Public Class Car
    Sub Drive()
        Console.WriteLine("Jedu")
    End Sub

    Dim speed As Integer
End Class

Tyto členy třídy mají takzvané modifikátory přístupu. Ty určují, odkud můžeme k dotyčnému členu přistupovat. Prvním modifikátorem přístupu je Public. Ke členům označeným jako Public můžeme přistupovat odkudkoli. Další možností je Friend. K členům s označením Friend můžeme přistupovat pouze z toho assembly, ve kterém je daná třída deklarována. Assembly (sestavení) je hotový, zkompilovaný soubor *.exe nebo *.dll. Třetím modifikátorem přístupu je Protected. Pokud označíte člen jako Protected, můžete k němu přistupovat pouze z té třídy, ve které je deklarován, a ze tříd, které z ní dědí (tento pojem si vysvětlíme později). Další modifikátor přístupu je Protected Friend, který je kombinací předchozích dvou. Ke členu, který má označení Protected Friend, můžeme přistupovat pouze ze třídy, ve které je deklarován, ze třídy, která od ní dědí, nebo ze třídy, která od ní sice nedědí, ale je deklarována ve stejném assembly. A posledním modifikátorem přístupu je Private, který značí, že k dotyčnému členu lze přistupovat pouze ze třídy, ve které je deklarovaný.

Nyní si vše, co jsme si řekli, předvedeme na praktické ukázce:

Public Class Car
    Private speed As Integer = 0

    Public Sub Accelerate(ByVal s As Integer)
        speed += s
        Console.WriteLine("Zrychluji na " & speed & " km/h.")
    End Sub

    Public Sub Deccelerate(ByVal s As Integer)
        speed -= s
        Console.WriteLine("Zpomaluji na " & speed & " km/h.")
    End Sub

    Public Sub StopCar()
        speed = 0
        Console.WriteLine("Zastavuji.")
    End Sub

    Public Sub Drive(ByVal s As Integer)
        speed = s
        Console.WriteLine("Jedu rychlostí " & s & " km/h.")
    End Sub
End Class

Jak třídu používat?

Pro použití třídy, kterou jsme právě napsali, musíme napřed vytvořit její instanci. Instance třídy je jako každá proměnná. Stejně jako vytvoříte proměnnou typu Integer, můžete vytvořit proměnnou typu Car. Instance se dá popsat jako živý objekt, zatímco třída je pouze popis. Třeba Člověk je pouze popis, ale Honza, Petr, Jana jsou instance třídy Člověk. Instanci vytvoříme klíčovým slovem New:

Dim ferrari As Car = New Car
'nebo zkráceně
Dim lamborghini As New Car

A nyní můžeme klidně volat metody, které jsme si v třídě napsali:

ferrari.Drive(150)
ferrari.Accelerate(50)
ferrari.Deccelerate(130)
ferrari.StopCar()

Vlastnosti

Jazyk VB.NET nabízí funkcionalitu pro přístup k proměnným třídy, a tou jsou vlastnosti. Vlastnost se značí klíčovým slovem Property a obsahuje dvě metody - Get a Set. Metoda Get se volá vždy, když z vlastnosti čteme, metoda Set vždy, když do ní zapisujeme:

Public Class Foo
    Private _bar As Integer

    Public Property Bar() As Integer
        Get
            Return _bar
        End Get
        Set(ByVal value As Integer)
            _bar = value
        End Set
    End Property
End Class

...

Dim f As New Foo
Dim i As Integer
f.Bar = 6 'Volá se metoda Set.
i = f.Bar 'Volá se funkce Get.

Pokud chcete deklarovat vlastnost pouze ke čtení, do které nebude možné zapisovat, vynechejte metodu Set a označte vlastnost klíčovým slovem ReadOnly:

Public ReadOnly Property Bar() As Integer
    Get
        Return _bar
    End Get
End Property

Mnozí začínající programátoři zprvu nechápou, proč používat vlastnosti a ne přímo proměnné označené jako Public. První důvod je, že data by měla být vždy soukromá a používání vlastností je doporučeno. Druhým, mnohem podstatnějším důvodem je: Co kdybyste chtěli provést třeba nějakou kontrolu, např. aby proměnná speed nemohla obsahovat zápornou hodnotu? Pro tento případ jsou vlastnosti naprosto ideální:

Public Property Speed() As Integer
    Get
        Return _speed
    End Get
    Set(ByVal value As Integer)
        If value >= 0 Then
            _speed = value
        Else
            _speed = 0
        End If
    End Set
End Property

Konstruktory a destruktory

Každá třída má dvě speciální metody: konstruktor a destruktor. Konstruktor je metoda, která je volaná vždy, když vytvoříte novou instanci třídy pomocí klíčového slova New. Konstruktor má (většinou) modifikátor přístupu Public a jeho jméno je vždy New:

Public Class Foo
    Public Sub New()

    End Sub
End Class

Konstruktor může (a nemusí) přijímat parametry:

Public Class Foo
    Private _bar, _baz As Integer

    Public Sub New(ByVal br As Integer, ByVal bz As Integer)
        _bar = br
        _baz = bz
    End Sub
End Class

'Inicilaizace třídy potom vypadá takto:
...
Dim f As New Foo(15, 30)

Ještě mě napadá něco, co jsem měl zmínit už při probírání metod: metody a funkce lze přetěžovat. To znamená, že můžete mít dvě metody, které se jmenují stejně, ale přebírají jiné argumenty nebo mají jinou návratovou hodnotu (např. můžete mít funkci Add, která přebírá dva Integery a vrací sečtený Integer a ve stejném modulu/třídě můžete mít druhou funkci Add, která přebírá dva Doubly a vrací sečtený Double). A stejně jako metody lze přetěžovat i konstruktory:

Public Class Foo
    Private _bar, _baz As Integer

    Public Sub New()
        _bar = 0
        _baz = 0
    End Sub

    Public Sub New(ByVal br As Integer)
        _bar = br
        _baz = 0
    End Sub

    Public Sub New(ByVal br As Integer, ByVal bz As Integer)
        _bar = br
        _baz = bz
    End Sub
End Class

Destruktor je metoda, která se volá v okamžiku, kdy se běhové prostředí (.NET) rozhodne, že instanci třídy není potřeba dále vydržovat, a vymaže ji z paměti. Destruktor nikdy nevoláte vy sami! Destruktor má pár pravidel: vždy se musí jmenovat Finalize(), vždy musí být označený jako Protected, vždy musí být označen klíčovým slovem Overrides (co toto klíčové slovo znamená, se dozvíme, až se budeme bavit o dědičnosti tříd) a nikdy nesmí přebírat jakékoli parametry. Takže destruktor naší třídy Foo musí vypadat takhle:

Public Class Foo
    ...
    Protected Overrides Sub Finalize()
        'Nějaký kód...
    End Sub
End Class

V drtivé většině případů nebudete vlastní destruktor potřebovat a bude stačit ten, který vám při kompilaci vygeneruje kompilátor jazyka VB.NET.

Hodnotové a refereční typy

Datové typy ve VB.NET se dělí na dvě skupiny: hodnotové a refereční. Mezi hodnotové typy patří například všechny primitivní typy kromě String, refereční je většina ostatních. Jaký že je mezi nimi rozdíl?

Paměť v počítači má dvě významné části: zásobník (stack) a haldu (heap). Kdykoli vytvoříte proměnnou hodnotového typu (např. Integer), vytvoří se na zásobníku schránka dostatečně velká na to, aby pojmula proměnnou konkrétního datového typu (tzn. pro datový typ Integer bude mít vytvořená schránka velikost 4 bajty). Takže si vytvoříme proměnnou typu Integer a dáme jí hodnotu 8. Na zásobníku se vytvoří schránka o velikosti 4 bajty a do ní se umístí předaná hodnota (8). Teď si vytvoříme další proměnnou typu Integer, které přiřadíme hodnotu té první proměnné. Co se stane? Na zásobníku se vytvoří další schránka, opět pro typ Integer a do ní se přiřadí hodnota schránky číslo 1, tj. 8. Takže nyní máme na zásobníku dva Integery a každý má hodnotu 8.

Oproti tomu refereční typy se chovají takto: Kdykoli vytvoříte novou instanci, třeba třídy Foo, vytvoří se na haldě schránka pro datový typ Foo a na zásobníku se vytvoří proměnná, která uchovává adresu schránky na haldě. A jak se ref. typy chovají při kopírování? Pokud vytvoříte novou proměnnou typu Foo, ale nepoužijete klíčové slovo New, nýbrž prostě vložíte proměnnou f1 do proměnné f2, vytvoří se na zásobníku schránka, ve které je odkaz na stejnou schránku na haldě jako ve schránce první. Čili obě proměnné nyní ukazují na stejné místo v paměti a pokud změníte jednu, změníte automaticky i druhou. Rozeberme si tento kód:

    Sub Main()
        Dim i As Integer = 8
        Dim j As Integer = i
        j += 1
        Console.WriteLine(i & " " & j)

        Dim c As New Car
        c.Speed = 150
        Dim d As Car = c
        d.Speed = 200
        Console.WriteLine(c.Speed)
    End Sub

Výstupem prvního Console.WriteLine bude: "8 9", přesně jak bychom čekali. Ale výstupem druhého bude: "200". Proč, když jsme vlastnost Speed proměnné c nastavili na 150? Protože do proměnné d jsme zkopírovali pouze adresu proměnné c (Car je referenční typ), takže změna čehokoli v proměnné d ovlivní i proměnnou c.

ByRef

Představte si tuto situaci: Chcete napsat metodu, která zvýší o jedničku Integer, který jí předáte jako parametr. Mohlo by to vypadat nějak takto:

    Sub Main()
        Dim j As Integer = 5
        AddOne(j)
        Console.WriteLine(j)
    End Sub

    Sub AddOne(ByVal i As Integer)
        i += 1
    End Sub

Ovšem pokud byste tento kód spustili, zjistíte, že proměnná j má stále hodnotu 5. Proč? Protože v metodě AddOne se vytvoří nový Integer i a my zvyšujeme o jedna hodnotu i, ne hodnotu j! Pokud by byl Integer referenční typ, fungovalo by to bez problému, ale jak to vyřešíme? Nahradíme slovo ByVal v deklaraci parametru slovem ByRef. To nám určuje, že s hodnotovým typem předaným této metodě se bude zacházet jako s referenčním:

    Sub Main()
        Dim j As Integer = 5
        AddOne(j)
        Console.WriteLine(j)
    End Sub

    Sub AddOne(ByRef i As Integer)
        i += 1
    End Sub

A funguje bez problému...

Tvorba vlastního hodnotového typu

Kdykoli vytvoříte novou třídu použitím klíčového slova Class, bude tato třída referenčního typu. Pokud byste chtěli vytvořit vlastní hodnotový typ, nemůžete jej deklarovat jako třídu, nýbrž jako strukturu. Struktura je vždy hodnotový typ a deklaruje se slovem Structure (pokud umístíte v IDE kurzor na slovo Integer a stisknete F12, uvidíte, že Integer je také struktura):

Public Structure Name
    Private _firstName, _lastName As String

    Public Property FirstName() As String
        Get
            Return _firstName
        End Get
        Set(ByVal value As String)
            _firstName = value
        End Set
    End Property

    Public Property LastName() As String
        Get
            Return _lastName
        End Get
        Set(ByVal value As String)
            _lastName = value
        End Set
    End Property

    Public Overrides Function ToString() As String
        Return _firstName & " " & _lastName
    End Function
End Structure

Struktura se od třídy (kromě způsobu předávání) příliš neliší, až na to, že struktura sice může mít konstruktor, ale tento musí vždy přijímat nějaké parametry, protože implicitní konstruktor (bez parametrů) vždy generuje kompilátor a takový konstruktor vždy inicializuje všechny členské proměnné struktury na defaultní hodnoty ("" pro String, 0 pro Integer, False pro Boolean apod.).

Upozornění: Struktury nikdy nepoužívejte pro velké objekty obsahující mnoho členských proměnných, protože při kopírování struktur se kopírují všechna data, ne jenom odkaz! Kopírování velkého množství dat může drasticky snížit výkon vašeho programu!

Tak, řekl bych, že jsme na konci tohoto dílu. Za domácí úkol se hlavně snažte pochopit vše, co jsem tu popsal, pokud chcete, vyberte si jakýkoli předmět ve vašem okolí (budík, televizi) a popište jej jako třídu. Dbejte na používání vlastností a data uchovávejte vždy soukromá! U dalšího dílu se těším na shledanou!


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