NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!
NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.

Lekce 10 - Vlastnosti ve Visual Basic .NET

V předešlém cvičení, Řešené úlohy k 9. lekci OOP ve VB.NET, jsme si procvičili nabyté zkušenosti z předchozích lekcí.

V dnešním VB.NET tutoriálu se podíváme na další prvky tříd, které ještě neznáme. Začněme slíbenými vlastnostmi.

Vlastnosti

Velmi často se nám stává, že chceme mít kontrolu nad změnami nějakého atributu objektu zvenčí. Budeme chtít atribut nastavit jako read-only nebo reagovat na jeho změny. Založme si nový projekt (název Vlastnosti) a vytvořme následující třídu Student, která bude reprezentovat studenta v nějakém informačním systému.

Class Student
    Public jmeno As String
    Public muz As Boolean
    Public vek As Integer
    Public plnolety As Boolean

    Public Sub New(jmeno As String, pohlavi As Boolean, vek As Integer)
        Me.jmeno = jmeno
        Me.muz = pohlavi
        Me.vek = vek
        plnolety = True
        If vek < 18 Then
            plnolety = False
        End If
    End Sub

    Public Overrides Function ToString() As String
        Dim jsemPlnolety As String = "jsem"
        If Not plnolety Then
            jsemPlnolety = "nejsem"
        End If
        Dim pohlavi As String = "muž"
        If Not muz Then
            pohlavi = "žena"
        End If
        Return String.Format("Jsem {0}, {1}. Je mi {2} let a {3} plnoletý.", jmeno, pohlavi, vek, jsemPlnolety)
    End Function

End Class

Třída je velmi jednoduchá, student se nějak jmenuje, je nějakého pohlaví a má určitý věk. Podle tohoto věku se nastavuje atribut plnolety pro pohodlnější vyhodnocování plnoletosti na různých místech systému. K uložení pohlaví používáme hodnotu Boolean, zda je student muž. Konstruktor dle věku určí, zda je student plnoletý. Metoda ToString() je navržena pro potřeby tutoriálu tak, aby nám vypsala všechny informace. V reálu by tam bylo pravděpodobně jen jméno studenta. Pomocí konstruktoru si nějakého studenta vytvořme:

Dim s As New Student("Pavel Hora", True, 20)
Console.WriteLine(s)

Výstup:

Konzolová aplikace
Jsem Pavel Hora, muž. Je mi 20 let a jsem plnoletý.

Vše vypadá hezky, ale atributy jsou přístupné jak ke čtení, tak k zápisu. Objekt tedy můžeme rozbít například takto (hovoříme o nekonzistentním vnitřním stavu):

Dim s As New Student("Pavel Hora", True, 20)
s.vek = 15
s.muz = False
Console.WriteLine(s)
Console.ReadKey()

Výstup:

Konzolová aplikace
Jsem Pavel Hora, žena. Je mi 15 let a jsem plnoletý.

Určitě musíme ošetřit, aby se plnoletost obnovila při změně věku. Když se zamyslíme nad ostatními atributy, není nejmenší důvod, abychom je taktéž umožňovali modifikovat. Student si za normálních okolností asi jen stěží změní pohlaví nebo jméno. Bylo by však zároveň vhodné je vystavit ke čtení, nemůžeme je tedy pouze pouze nastavit jako Private. V dřívějších dílech seriálu jsme k tomuto účelu používaly metody, které sloužily ke čtení privátních atributů. Jejich název jsme volili jako VratVek() a podobně. Ke čtení vybraných atributů vytvoříme také metody a atributy označíme jako privátní. Třída by nově vypadala např. takto (vynechal jsem konstruktor a ToString()):

Class Student
    Private jmeno As String
    Private muz As Boolean
    Private vek As Integer
    Private plnolety As Boolean

    ...

    Public Function VratJmeno() As String
        Return jmeno
    End Function

    Public Function VratPlnoletost() As Boolean
        Return plnolety
    End Function

    Public Function VratVek() As Integer
        Return vek
    End Function

    Public Function Muz() As String
        Return muz
    End Function

    Public Sub NastavVek(hodnota As Integer)
        vek = hodnota
        ' přehodnocení plnoletosti
        plnolety = True
        If vek < 18 Then
            plnolety = False
        End If
    End Sub


End Class

Metody, co hodnoty jen vracejí, jsou velmi jednoduché. Nastavení věku má již nějakou vnitřní logiku, při jeho změně musíme totiž přehodnotit atribut plnolety. Zajistili jsme, že se do proměnných nedá zapisovat jinak, než my chceme. Máme tedy pod kontrolou všechny změny atributů a dokážeme na ně reagovat. Nemůže se stát, že by nám někdo vnitřní stav nekontrolovaně měnil a rozbil.

Metodám k navrácení hodnoty se říká gettery a metodám pro zápis settery. Pro editaci ostatních atributů bychom udělali jednu metodu EditujStudenta, která by byla podobná konstruktoru. Jméno, věk a podobně by se tedy měnily pomocí této metody, tam bychom mohli např. konstrolovat, zda hodnoty dávají smysl, opět bychom odchytili všechny pokusy o změnu na jediném místě. Ruční psaní getterů a setterů je jistě velmi pracné. Nemohl by to udělat někdo za nás? Ano, VB.NET nám je umí vygenerovat. Poté již nehovoříme o atributech, ale o vlastnostech.

Syntaxe vlastnosti je velmi podobná atributu:

Public Property Jmeno As String

Zprvu to vypadá, jako bychom deklarovali atribut. Jméno vlastnosti je však velkým písmenem, jedná se totiž o metodu (přesněji 2 metody). Ještě k deklaraci musíme přidat klíčové slovo Property. V ukázce výše se vygeneruje setter i getter, vlastnost půjde tedy normálně číst i modifikovat:

Console.WriteLine(objekt.Jmeno)' číst
objekt.Jmeno = "Jan Malý"' zapisovat

Jediný rozdíl oproti atributu je zvenčí v tom, že počáteční písmeno je velké. VB.NET ve skutečnosti vygeneruje privátní atribut a k němu dvě metody, které podle kontextu volá (pozná dle situace zda čteme nebo zapisujeme). Pokud chceme uvést vlastní setter a getter, je syntaxe následující:

Private _jmeno As String
Public Property Jmeno As String
    Get
        Return _jmeno
    End Get
    Set(value As String)
        _jmeno = value
    End Set
End Property

U vlastní deklarace si hodnotu ještě někde musíme pamatovat, dává se do privátního atributu, obvykle ho pojmenujeme podtržítko a název vlastnosti s malým počátečním písmenem.

Když do vlastnosti nevygenerujeme setter, nepůjde měnit ani zevnitř, ani zvenčí. Pokud si přejeme, aby vlastnost nešla mimo třídu měnit, označíme setter jako privátní:

Public Property Jmeno() As String
    Get
        Return _jmeno
    End Get
    Private Set(value As String)
        _jmeno = Value
    End Set
End Property
Private _jmeno As String

Tohoto budeme hojně využívat a právě takto bude vypadat většina vlastností našich budoucích tříd.

V getteru nebo setteru se toho může samozřejmě dělat více, než jen načtení/zápis hodnoty, pokud si ho definujeme ručně. Ukažme si to na našem příkladu s plnoletostí, která se musí po změně věku přehodnotit:

Private _vek As Integer
Public Property Vek() As Integer
    Get
        Return _vek
    End Get
    Set(value As Integer)
        _vek = value
        ' kontrola plnoletosti
        Plnolety = True
        If _vek < 18 Then
            Plnolety = False
        End If
    End Set
End Property

Zprvu je nutné si vytvořit privátní proměnnou vek s malým písmenem, ve které bude hodnota ve skutečnosti uložena. V getteru a setteru poté pracujeme s touto proměnnou, pokud použijete v get nebo set Vek, program se zacyklí!. Není možné definovat jen getter nebo setter, buď se oba vygenerují sami nebo oba definujeme ručně. Pro přístup k zadané hodnotě je nám v setteru k dispozici klíčové slovo Value. Takto se ve VB.NET do verze 4.0 musely definovat všechny vlastnosti, až poté Microsoft zavedl tzv. autoimplementaci a zkrácený zápis, jaký jsme si uvedli výše. U drtivé většiny vlastností totiž v metodách nepotřebujeme žádnou logiku. S Vek nyní pracujeme opět stejně, jako s atributem, jen s velkým písmenem. Nenápadné přiřazení do věku vnitřně spustí další logiku k přehodnocení vlastnosti Plnolety:

objekt.Vek = 15 ' nyní se změní i plnoletost

Stejně můžeme pochopitelně implementovat i getter a například něco někam logovat.

Upravíme si naši třídu Student tak, aby používala vlastnosti. Vypadala by takto:

Class Student

    Private _jmeno As String
    Public Property Jmeno() As String
        Get
            Return _jmeno
        End Get
        Private Set(value As String)
            _jmeno = Value
        End Set
    End Property

    Private _muz As Boolean
    Public Property Muz() As Boolean
        Get
            Return _muz
        End Get
        Private Set(value As Boolean)
            _muz = Value
        End Set
    End Property

    Private _plnolety As Boolean
    Public Property Plnolety() As Boolean
        Get
            Return _plnolety
        End Get
        Private Set(value As Boolean)
            _plnolety = Value
        End Set
    End Property

    Private _vek As Integer
    Public Property Vek() As Integer
        Get
            Return _vek
        End Get
        Set(value As Integer)
            _vek = value
            ' kontrola plnoletosti
            Plnolety = True
            If _vek < 18 Then
                Plnolety = False
            End If
        End Set
    End Property

    Public Sub New(jmeno As String, pohlavi As Boolean, vek As Integer)
        EditujStudenta(jmeno, pohlavi, vek)
    End Sub

    Public Sub EditujStudenta(jmeno As String, muz As Boolean, vek As Integer)
        Me.Jmeno = jmeno
        Me.Muz = muz
        Me.Vek = vek
    End Sub

    Public Overrides Function ToString() As String
        Dim jsemPlnolety As String = "jsem"
        If Not Plnolety Then
            jsemPlnolety = "nejsem"
        End If
        Dim pohlavi As String = "muž"
        If Not Muz Then
            pohlavi = "žena"
        End If
        Return String.Format("Jsem {0}, {1}. Je mi {2} let a {3} plnoletý.", jmeno, pohlavi, vek, jsemPlnolety)
    End Function

End Class

Vlastnosti budeme odteď používat stále, umožňují nám totiž objekty dokonale zapouzdřit. V .NET jsou všechny veřejné atributy tříd vlastnosti (např. nám známá vlastnost Length na stringu), platí pravidlo, že co jde ven je vlastnost, co se používá jen uvnitř je privátní atribut. Veřejný atribut se defakto příliš nepoužívá. Celou třídu i s ukázkovým programem si samozřejmě opět můžete stáhnout pod článkem. Kontrolu plnoletosti můžeme z konstruktoru nyní vyjmout, jakmile totiž dosadíme do vlastnosti Vek, nastaví se plnoletost sama. Ještě si opět vyzkoušejme problémový příklad:

Dim s As New Student("Pavel Hora", True, 20)
s.vek = 15
' s.pohlavi = False ' tento řádek nyní způsobí chybu a musí být odebrán
Console.WriteLine(s)

A výstup:

Konzolová aplikace
Jsem Pavel Hora, muž. Je mi 15 let a nejsem plnoletý.

Pokud celou vlastnost označíme jako private, nelze poté settery nebo gettery označit jako public.

V následujícím kvízu, Kvíz - Dědičnost, statika, vlastnosti ve VB.NET OOP, si vyzkoušíme nabyté zkušenosti z předchozích lekcí.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

Staženo 188x (58.29 kB)
Aplikace je včetně zdrojových kódů v jazyce VB

 

Předchozí článek
Řešené úlohy k 9. lekci OOP ve VB.NET
Všechny články v sekci
Objektově orientované programování ve Visual Basic .NET
Přeskočit článek
(nedoporučujeme)
Kvíz - Dědičnost, statika, vlastnosti ve VB.NET OOP
Článek pro vás napsal Michal Žůrek - misaz
Avatar
Uživatelské hodnocení:
10 hlasů
Autor se věnuje tvorbě aplikací pro počítače, mobilní telefony, mikroprocesory a tvorbě webových stránek a webových aplikací. Nejraději programuje ve Visual Basicu a TypeScript. Ovládá HTML, CSS, JavaScript, TypeScript, C# a Visual Basic.
Aktivity