10. díl - Vlastnosti ve Visual Basic .NET

Ostatní jazyky Visual Basic .NET Objektově orientované programování Vlastnosti ve Visual Basic .NET

V minulém dílu seriálu tutoriálů o VB.NET jsem si vysvětlili statiku. Dnes 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:

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):

copy to clipboard | view source | convert again
Dim s As New Student("Pavel Hora", True, 20)
s.vek = 15
s.muz = False
Console.WriteLine(s)
Console.ReadKey()

Výstup:

Vlastnosti tedy gettery a settery VB.NET

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(ByVal 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 getter jako privátní:

Public Property Jmeno() As String
        Get
                Return _jmeno
        End Get
        Private Set
                _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 ůž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 (opět bez konstruktoru a ToStringu):

Class Student
        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
        Public Property Muz() As Boolean
                Get
                        Return _muz
                End Get
                Private Set(value As Boolean)
                        _muz = Value
                End Set
        End Property
        Private _muz As Boolean
        Public Property Plnolety() As Boolean
                Get
                        Return _plnolety
                End Get
                Private Set(value As Boolean)
                        _plnolety = Value
                End Set
        End Property
        Private _plnolety As Boolean
        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

        ...

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
Console.WriteLine(s)

A výstup:

Vlastnosti tedy gettery a settery Visual Basic .NET

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

Příště se podíváme, jak se v .NET pracuje s datem a časem.


 

Stáhnout

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

 

  Aktivity (1)

Článek pro vás napsal Michal Žůrek (misaz)
Avatar
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.

Jak se ti líbí článek?
Celkem (2 hlasů) :
55555


 



 

 

Komentáře

Avatar
Jaroslav Trojan:

Upravené Vlastnosti:

Module Module1

Sub Main()
Dim s As New Student("Pavel Hora", True, 20)
's.Vek = 15
' s.muz = True
Console.Write­Line(s)

' Console.Write­Line(objekt, Jmeno) 'číst
' objekt.Jmeno = "Jan Malý" 'zapisovat

Console.ReadKey()
End Sub

End Module

upravená třída Student:

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 = Muz
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 True Then
pohlavi = "žena"
Else
pohlavi = "muž"
End If
Return [String].Format("Jsem {0}, {1}.Je mi {2} let a {3} plnoletý.", Jmeno, pohlavi, Vek, jsemPlnolety)
End Function
Public Function VratJmeno() As String
Return jmeno
End Function

Public Function VratPlnoletost() As String
Return plnolety
End Function
Public Function VratVek() As Integer
Return vek
End Function
Public Function Muz1() 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
' 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
'Public Property Muz() As Boolean
'Get
'Return Muz
'End Get
'Private Set(value As Boolean)
' muz = value
'End Set
' End Property
' Private muz As Boolean
'Public Property Plnolety() As Boolean
'Get
'Return Plnolety
'End Get
'Private Set(value As Boolean)
' plnolety = value
'End Set
'End Property
' Private plnolety As Boolean
' 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

' část Property nefunguje, hlásí chyby!
' vyřadil jsem ji

End Class

ostatní pracuje dobře!

 
Odpovědět 3. července 15:28
Avatar
Jaroslav Trojan:

Ta třída Student stále nefunguje správně, pro nastavený věk 15 let vypíše: jsem plnoletý proč?
Když tam ponechám část Property s gettery a settery tak to hlásí spoustu chyb

 
Odpovědět 8. července 13:06
Avatar
Odpovědět 8. července 18:06
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
VitekST
Člen
Avatar
Odpovídá na Jaroslav Trojan
VitekST:

Co to má co dělat tady? Na to slouží diskuzní fórum, ne komentáře pod příspěvkem.
Navíc, dotaz jsem zodpověděl.

 
Odpovědět 8. července 18:08
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 4 zpráv z 4.