2. diel - Prvá objektová aplikácia v C# - Hello object world
V minulej lekcii, Úvod do objektovo orientovaného programovania v C#, sme si predstavili úvod do objektovo orientovaného programovania.
Už vieme, že objekty majú atribúty a metódy. Tiež vieme, že na vytvorenie objektu potrebujeme najskôr vytvoriť triedu. Tá je vzorom, podľa ktorého následne tvoríme jej inštancie.
Na začiatku kurzu so základnými konštrukciami jazyka C# sme si vytvorili program Hello world. Urobme si teraz podobný program ako úvod do objektovo orientovaného programovania. Naprogramujme si Hello object world!
Vo Visual Studiu si založme novú konzolovú aplikáciu tak, ako sme to robili doteraz. V Solution Exploreri napravo klikneme pravým tlačidlom myši na náš projekt a vyberieme Add -> Class…. Ide to aj klávesovou skratkou Shift + Alt + C :
Class pomenujeme Greeter.cs
a potvrdíme. Názov triedy píšeme
vždy ťavou notáciou bez medzier a na rozdiel od premenných má každé slovo
veľké prvé písmeno, teda aj to prvé. Názov je samozrejme tiež bez
diakritiky, tú v programe používame maximálne vo vnútri textových
reťazcov, nie v identifikátoroch:
Podľa tejto triedy neskôr vytvoríme objekt greeter
, ktorý
nás bude vedieť pozdraviť. Vidíme, že sa na program už pozeráme úplne
inak. Za každú akciu je zodpovedný nejaký objekt, nestačí iba niečo
"nabúšiť" do Main()
. V tomto prípade nám to môže pripadať
zbytočné, pri zložitejších aplikáciách si to však budeme pochvaľovať
V našom Solution Exploreri pribudne ďalší súbor .cs
a VS
nám ho otvorí. K pôvodnému Program.cs
s metódou
Main()
sa môžeme vrátiť pomocou záložky alebo cez Solution
Explorer.
Pozrime sa, čo nám VS vygenerovalo, a kód si popíšme. Následne si do triedy pridáme vlastnú metódu na pozdravenie:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace HelloObjects { class Greeter { } }
Kľúčové slovo namespace
nám označuje tzv.
menný priestor. Rovnako ako sa metódy združujú do tried, tak sa aj triedy
združujú do menných priestorov. Ak chceme, aby bola naša trieda viditeľná
aj v Program.cs
, kde máme metódu Main()
, musíme
mať triedu v rovnakom mennom priestore. To tu platí, VS samo novú triedu
obalí tým istým menným priestorom. My namiesto HelloObjects
budeme mať názov svojej aplikácie. Ak sme ju nepomenovali, bude tam
ConsoleApplication1
.
Príkaz using
nám umožňuje zviditeľniť
triedy iných menných priestorov, aby sme s nimi mohli pracovať. V základe
nám VS pripraví System
, potom generické kolekcie, teda
Linq
a Text
. Pre nás bude najdôležitejšie menné
priestory namespace
System
, pretože práve ten
obsahuje triedu Console
. Ďalšie menné priestory využijeme až
neskôr. Potom budeme dokonca potrebovať nejaké menné priestory dodať,
najmä na prácu s textovými súbormi.
V namespace
je teda umiestnená samotná trieda, ktorá sa
deklaruje kľúčovým slovom class
. Trieda sa volá
Greeter
a je prázdna.
Všimnime si, že kód je takmer rovnaký ako ten v Program.cs
,
už teda rozumieme tomu, čo sme predtým ignorovali. Náš konzolový program
bola vlastne trieda umiestnená v mennom priestore, ktorá obsahovala jednu
metódu Main()
. Vidíme, že v C# sa v podstate neobjektovo
programovať ani nedá, čo je len dobre
Teraz si do triedy Greeter
pridáme metódu
Greet()
. Tá bude verejne viditeľná a nebude mať žiadnu
návratovú hodnotu ani parametre.
Deklarácia metódy v C# je teda nasledujúca:
[Access modifier] [return type] [MethodName]([parameters])
Pred metódou bude tzv. modifikátor prístupu, v našom prípade
public
(verejná). Keby sme modifikátor
vynechali, jazyk C# by metódu chápal ako private
(neverejnú).
Metóda nebude vracať žiadnu hodnotu, čo docielime kľúčovým slovom
void
. Ďalej bude nasledovať samotný názov
metódy, ktoré píšeme rovnako ako triedy ťavej notácií s veľkým
počiatočným písmenom. Prvé písmeno názvu je však na rozdiel od
premenných veľké! Zátvorka s parametrami je povinná. My ju necháme
prázdnu, pretože metóda žiadne parametre mať nebude. Do tela metódy
zapíšeme kód pre výpis na konzole.
Naša trieda bude teraz vyzerať takto:
class Greeter { public void Greet() { Console.WriteLine("Hello object world!"); } }
Tu sme zatiaľ skončili, prejdeme do Program.cs
.
Teraz si v tele metódy Main()
vytvoríme
inštanciu triedy Greeter
. Bude to teda ten objekt
greeter
, s ktorým budeme pracovať. Objekty sa ukladajú do
premenných, názov triedy slúži ako dátový typ. Inštancia má spravidla
názov triedy, iba má prvé písmeno malé. Deklarujme si premennú a následne
v nej založme novú inštanciu triedy Greeter
:
Greeter greeter;
greeter = new Greeter();
Prvý riadok hovorí: "Chcem premennú greeter
, v ktorej bude
inštancia triedy Greeter
." S premennými sme vlastne už takto
pracovali.
Na druhom riadku je kľúčové slovo new
,
ktoré nám založí novú inštanciu triedy Greeter
. Túto
inštanciu priradíme k našej premennej.
Pri vytvorení novej inštancie sa zavolá tzv. konštruktor, čo je špeciálna metóda na triede. Preto pri vytvorení inštancie píšeme ony prázdne zátvorky, pretože voláme túto "vytváraciu" metódu. Konštruktor spravidla obsahuje nejakú inicializáciu vnútorného stavu inštancie (napr. dosadí východiskové hodnoty do premenných). Keďže sme v kóde žiadny konštruktor nedeklarovali, C# si vytvoril tzv. implicitný bezparametrický konštruktor. Vytvorenie inštancie objektu sa teda podobá volaniu metódy. Celý zápis môžeme samozrejme skrátiť na:
Greeter greeter = new Greeter();
Od .NET 5 už nemusíme typ druhýkrát vypisovať, ale zapíšeme len:
Greeter greeter = new();
Tento zápis používame iba v prípade, keď je jasne poznať, akého typu premenná je. Tiež zatiaľ nie je podporovaný online kompilery na sieti.
Keďže v premennej teraz máme naozaj inštanciu triedy
Greeter
, môžeme inštanciu nechať pozdraviť. Zavoláme na ňu
metódu Greet()
, a to ako greeter.Greet()
. K
aplikácii pridáme ešte Console.ReadKey()
. Kód metódy
Main()
bude teda teraz vyzerať nasledovne:
{CSHARP_CONSOLE} Greeter greeter = new Greeter(); greeter.Greet(); Console.ReadKey(); {/CSHARP_CONSOLE}
{CSHARP_OOP} class Greeter { public void Greet() { Console.WriteLine("Hello object world!"); } } {/CSHARP_OOP}
Program spustíme:
Our first object-oriented application
Hello object world!
Máme teda svoju prvú objektovú aplikáciu!
Dajme teraz našej metóde Greet()
parameter name
,
aby dokázala pozdraviť konkrétneho užívateľa:
public void Greet(string name) { Console.WriteLine("Hi user {0}", name); }
Vidíme, že syntax parametra metódy je rovnaká ako syntax premennej. Keby
sme chceli parametrov viac, oddeľujeme ich čiarkou. Teraz upravíme našu
metódu Main()
:
{CSHARP_CONSOLE} Greeter greeter = new Greeter(); greeter.Greet("Carl"); greeter.Greet("Peter"); Console.ReadKey(); {/CSHARP_CONSOLE}
{CSHARP_OOP} class Greeter { public void Greet(string name) { Console.WriteLine("Hi user {0}", name); } } {/CSHARP_OOP}
Náš kód je teraz v metóde a my ho môžeme jednoducho pomocou parametrov volať znova s rôznymi parametrami. Nemusíme dvakrát opisovať "Hi user...". Kód budeme odteraz deliť logicky do metód:
Konzolová aplikácia
Hi user Carl
Hi user Peter
Triede pridáme nejaký atribút. Ponúka sa text
, kde bude
uložený text pozdravu. Atribúty sa definujú rovnako ako premenné. Ako pri
metódach platí, že pred atribútmi píšeme modifikátor prístupu, bez neho
ich C# berie ako private
. Upravme našu triedu:
class Greeter { public string text; public void Greet(string name) { Console.WriteLine("{0} {1}", text, name); } }
Text teraz pochopiteľne musíme nastaviť vytvorené inštanciu v
Program.cs
:
{CSHARP_CONSOLE} Greeter greeter = new Greeter(); greeter.text = "Hi user"; greeter.Greet("Carl"); greeter.Greet("Peter"); greeter.text = "Hello programmer"; greeter.Greet("Richard"); Console.ReadKey(); {/CSHARP_CONSOLE}
{CSHARP_OOP} class Greeter { public string text; public void Greet(string name) { Console.WriteLine("{0} {1}", text, name); } } {/CSHARP_OOP}
Konzolová aplikácia
Hi user Carl
Hi user Peter
Hello programmer Richard
Vzhľadom k objektovému návrhu nie je najvhodnejšie, aby každý objekt
ovplyvňoval vstup a výstup, ako sa mu zachce. Pochopiteľne narážame na
naše vypisovanie do konzoly. Každý objekt by mal mať určitú kompetenciu a
tú by nemal prekračovať. Poverme preto náš objekt iba zostavením pozdravu
a jeho výpis si spracujme už mimo, v našom prípade v metóde
Main()
. Výhodou takto navrhnutého objektu je vysoká
univerzálnosť a znovupoužiteľnosť. Objekt doteraz vie len písať do
konzoly, my ho však prispôsobíme tak, aby daná metóda text iba vracala a
aby bolo na jeho príjemcovi, ako s ním naložia. Takto môžeme pozdravy
ukladať do súborov, písať na webové stránky alebo ďalej
spracovávať.
Keďže chceme, aby metóda vracala hodnotu, a síce string
,
zmeníme jej doterajší typ void
na string
. Na
návrat hodnoty použijeme príkaz return
. Return
metódu ukončí a vráti hodnotu. Akýkoľvek kód v tele metódy po
return
sa už nevykoná! Upravme obe triedy:
Metóda Greet()
v Greeter.cs
:
public string Greet(string name) { return String.Format("{0} {1}", text, name); }
Telo metódy Main()
v Program.cs
:
{CSHARP_CONSOLE} Greeter greeter = new Greeter(); greeter.text = "Hi user"; Console.WriteLine(greeter.Greet("Carl")); Console.WriteLine(greeter.Greet("Peter")); greeter.text = "Hello programmer"; Console.WriteLine(greeter.Greet("Richard")); Console.ReadKey(); {/CSHARP_CONSOLE}
{CSHARP_OOP} class Greeter { public string text; public string Greet(string name) { return String.Format("{0} {1}", text, name); } } {/CSHARP_OOP}
Teraz je náš kód napísaný podľa dobrých praktík. Našu triedu ešte
okomentujme, ako sa pristane a patrí. Komentáre budeme písať nad názov
triedy a nad názov každého atribútu a metódy. Na ich zápis použijeme
trojlomítko ///
, VS nám potom vygeneruje XML, do ktorého všetko
popíšeme. Oplatí sa nám to vo chvíli, keď na triede používame nejakú
metódu. Jej popis sa nám potom zobrazí v našepkávači. Ak by nám
komentáre v kóde vadili (zaberajú predsa len niekoľko riadkov), môžeme ich
sklapnúť pomocou malých tlačidiel "-"
. Zdokumentovaná trieda
môže vyzerať napr. takto:
/// <summary> /// A class represents a greeter whose purpose is to greet the user /// </summary> class Greeter { /// <summary> /// Greeting text /// </summary> public string text; /// <summary> /// Greets the user with the stored greeting and his/her name /// </summary> /// <param name="name">The user's name</param> /// <returns>The greeting text</returns> public string Greet(string name) { return String.Format("{0} {1}", text, name); } }
Vidíme, že nám VS popisky naozaj zobrazia:
A sme na konci. Nami napísaný program má už nejakú úroveň, aj keď vlastne nič nerobí. Za úlohu máte prerobiť si našu konzolovú kalkulačku do objektov.
V nasledujúcom cvičení, Riešené úlohy k 1.-2. lekcii OOP v C# .NET, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 3x (50.02 kB)
Aplikácia je vrátane zdrojových kódov v jazyku C#