Lekce 2 - První objektová aplikace v C# - Hello object world
V minulé lekci, Úvod do objektově orientovaného programování v C#, jsme si představili úvod do objektově orientovaného programování.
Již víme, že objekty mají atributy a metody. Také víme, že k vytvoření objektu potřebujeme nejprve vytvořit třídu. Ta je vzorem, podle něhož následně tvoříme její instance.
Na začátku kurzu se základními konstrukcemi jazyka C# jsme si vytvořili program Hello world. Udělejme si nyní podobný program jako úvod do objektově orientovaného programování. Naprogramujme si Hello object world!
Ve Visual Studiu si teď založíme novou konzolovou aplikaci. Po spuštění VS se nám zobrazí následující okno, kde vybereme Create a new project pro vytvoření nového projektu:
Na další stránce si najdeme konzolovou aplikaci, vybereme ji a pokračujeme stisknutím Next:
Jako jméno aplikace zvolíme HelloObjects
. U lokace vybereme
složku C:\Users\vase_jmeno\Dropbox\Csharp\
:
Po opětovném kliknutí na Next se dostaneme na stránku s výběrem frameworku (implementace .NET). Výběr necháme na nejnovějším možném (v našem případě .NET 6.0) a zaškrtneme checkbox Do not use top-level statements:
Vytvoření projektu už jen potvrdíme kliknutím na tlačítko Create.
V hlavičce třídy Program
odstraníme modifikátor přístupu
internal
a v těle metody Main()
příkaz
Console.WriteLine("Hello, World!");
, jak vidíme na následujícím
obrázku.
V Solution Exploreru napravo klikneme pravým tlačítkem myši na náš projekt a vybereme Add -> Class…. Jde to i klávesovou zkratkou Shift + Alt + C:
Class pojmenujeme Zdravic.cs
a potvrdíme. Název třídy
píšeme vždy velbloudí notací bez mezer a na rozdíl od proměnných má
každé slovo velké první písmeno, tedy i to první. Název je samozřejmě
také bez diakritiky, tu v programu používáme maximálně uvnitř textových
řetězců, nikoli v identifikátorech:
Podle této třídy později vytvoříme objekt zdravic
, který
nás bude umět pozdravit. Vidíme, že se na program již díváme úplně
jinak. Za každou akci je zodpovědný nějaký objekt, nestačí pouze něco
"nabušit" do Main()
. V tomto případě nám to může připadat
zbytečné, u složitějších aplikací si to však budeme pochvalovat
V našem Solution Exploreru přibude další soubor .cs
a VS
nám ho otevře. K původnímu Program.cs
s metodou
Main()
se můžeme vrátit pomocí záložky nebo přes Solution
Explorer.
Podívejme se, co nám VS vygenerovalo, a kód si popišme. Následně si do třídy přidáme vlastní metodu pro pozdravení:
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace HelloObjects { class Zdravic { } }
Klíčové slovo namespace
nám označuje tzv.
jmenný prostor. Stejně jako se metody sdružují do tříd, tak se také
třídy sdružují do jmenných prostorů. Pokud chceme, aby byla naše třída
viditelná i v Program.cs
, kde máme metodu Main()
,
musíme mít třídu ve stejném jmenném prostoru. To zde platí, VS samo novou
třídu obalí týmž jmenným prostorem. My místo HelloObjects
budeme mít název své aplikace. Pokud jsme ji nepojmenovali, bude tam
ConsoleApplication1
.
Příkaz using
nám umožňuje zviditelnit
třídy jiných jmenných prostorů, abychom s nimi mohli pracovat. V základu
nám VS připraví System
, poté generické kolekce, tedy
Linq
a Text
. Pro nás bude nejdůležitější jmenné
prostory namespace
System
, protože právě ten
obsahuje třídu Console
. Další jmenné prostory využijeme až
později. Poté budeme dokonce potřebovat nějaké jmenné prostory dodat,
zejména pro práci s textovými soubory.
V namespace
je tedy umístěná samotná třída, která se
deklaruje klíčovým slovem class
. Třída se jmenuje
Zdravic
a je prázdná.
Povšimněme si, že kód je téměř stejný jako ten v
Program.cs
, již tedy rozumíme tomu, co jsme předtím ignorovali.
Náš konzolový program byla vlastně třída umístěná ve jmenném prostoru,
která obsahovala jednu metodu Main()
. Vidíme, že v C# se v
podstatě neobjektově programovat ani nedá, což je jen dobře
Nyní si do třídy Zdravic
přidáme metodu
Pozdrav()
. Ta bude veřejně viditelná a nebude mít žádnou
návratovou hodnotu ani parametry.
Deklarace metody v C# je tedy následující:
[modifikátor přístupu] [návratový typ] [JmenoMetody]([parametry])
Před metodou bude tzv. modifikátor přístupu, v našem případě
public
(veřejná). Kdybychom modifikátor
vynechali, jazyk C# by metodu chápal jako private
(neveřejnou).
Metoda nebude vracet žádnou hodnotu, čehož docílíme klíčovým slovem
void
. Dále bude následovat samotný název
metody, které píšeme stejně jako třídy velbloudí notací s velkým
počátečním písmenem. První písmeno názvu je však na rozdíl od
proměnných velké! Závorka s parametry je povinná. My ji necháme prázdnou,
protože metoda žádné parametry mít nebude. Do těla metody zapíšeme kód
pro výpis na konzoli.
Naše třída bude nyní vypadat takto:
class Zdravic { public void Pozdrav() { Console.WriteLine("Hello object world!"); } }
Zde jsme prozatím skončili, přejdeme do Program.cs
.
Nyní si v těle metody Main()
vytvoříme
instanci třídy Zdravic
. Bude to tedy ten objekt
zdravic
, se kterým budeme pracovat. Objekty se ukládají do
proměnných, název třídy slouží jako datový typ. Instance má zpravidla
název třídy, jenom má první písmeno malé. Deklarujme si proměnnou a
následně v ní založme novou instanci třídy Zdravic
:
Zdravic zdravic;
zdravic = new Zdravic();
První řádek říká: "Chci proměnnou zdravic
, ve které bude
instance třídy Zdravic
." S proměnnými jsme vlastně již takto
pracovali.
Na druhém řádku je klíčové slovo new
,
které nám založí novou instanci třídy Zdravic
. Tuto instanci
přiřadíme k naší proměnné.
Při vytvoření nové instance se zavolá tzv. konstruktor, což je speciální metoda na třídě. Proto při vytvoření instance píšeme ony prázdné závorky, jelikož voláme tuto "vytvářecí" metodu. Konstruktor zpravidla obsahuje nějakou inicializaci vnitřního stavu instance (např. dosadí výchozí hodnoty do proměnných). Poněvadž jsme v kódu žádný konstruktor nedeklarovali, C# si vytvořil tzv. implicitní bezparametrický konstruktor. Vytvoření instance objektu se tedy podobá volání metody. Celý zápis můžeme samozřejmě zkrátit na:
Zdravic zdravic = new Zdravic();
Od .NET 5 již nemusíme typ podruhé vypisovat, ale zapíšeme jen:
Zdravic zdravic = new();
Tento zápis používáme pouze v případě, kdy je jasně poznat, jakého typu proměnná je. Také zatím není podporován online kompilery na síti.
Jelikož v proměnné nyní máme opravdu instanci třídy
Zdravic
, můžeme instanci nechat pozdravit. Zavoláme na ni metodu
Pozdrav()
, a to jako zdravic.Pozdrav()
. K aplikaci
přidáme ještě Console.ReadKey()
. Kód metody
Main()
bude tedy nyní vypadat následovně:
{CSHARP_CONSOLE} Zdravic zdravic = new Zdravic(); zdravic.Pozdrav(); Console.ReadKey(); {/CSHARP_CONSOLE}
{CSHARP_OOP} class Zdravic { public void Pozdrav() { Console.WriteLine("Hello object world!"); } } {/CSHARP_OOP}
Program spustíme.
Naše první objektová aplikace
Hello object world!
Máme tedy svou první objektovou aplikaci!
Dejme nyní naší metodě Pozdrav()
parametr
jmeno
, aby dokázala pozdravit konkrétního uživatele:
public void Pozdrav(string jmeno) { Console.WriteLine("Ahoj uživateli {0}", jmeno); }
Vidíme, že syntaxe parametru metody je stejná jako syntaxe proměnné.
Kdybychom chtěli parametrů více, oddělujeme je čárkou. Nyní upravíme
naši metodu Main()
:
{CSHARP_CONSOLE} Zdravic zdravic = new Zdravic(); zdravic.Pozdrav("Karel"); zdravic.Pozdrav("Petr"); Console.ReadKey(); {/CSHARP_CONSOLE}
{CSHARP_OOP} class Zdravic { public void Pozdrav(string jmeno) { Console.WriteLine("Ahoj uživateli {0}", jmeno); } } {/CSHARP_OOP}
Náš kód je nyní v metodě a my ho můžeme jednoduše pomocí parametrů volat znovu s různými parametry. Nemusíme dvakrát opisovat "Ahoj uživateli...". Kód budeme odteď dělit logicky do metod.
Konzolová aplikace
Ahoj uživateli Karel
Ahoj uživateli Petr
Třídě přidáme nějaký atribut. Nabízí se text
, kde bude
uložen text pozdravu. Atributy se definují stejně jako proměnné. Jako u
metod platí, že před atributy píšeme modifikátor přístupu, bez něj je
C# bere jako private
. Upravme naši třídu:
class Zdravic { public string text; public void Pozdrav(string jmeno) { Console.WriteLine("{0} {1}", text, jmeno); } }
Text nyní pochopitelně musíme nastavit vytvořené instanci v
Program.cs
:
{CSHARP_CONSOLE} Zdravic zdravic = new Zdravic(); zdravic.text = "Ahoj uživateli"; zdravic.Pozdrav("Karel"); zdravic.Pozdrav("Petr"); zdravic.text = "Vítám tě tu programátore"; zdravic.Pozdrav("Richard"); Console.ReadKey(); {/CSHARP_CONSOLE}
{CSHARP_OOP} class Zdravic { public string text; public void Pozdrav(string jmeno) { Console.WriteLine("{0} {1}", text, jmeno); } } {/CSHARP_OOP}
Konzolová aplikace
Ahoj uživateli Karel
Ahoj uživateli Petr
Vítám tě tu programátore Richard
Vzhledem k objektovému návrhu není nejvhodnější, aby každý objekt
ovlivňoval vstup a výstup, jak se mu zachce. Pochopitelně narážíme na
naše vypisování do konzole. Každý objekt by měl mít určitou kompetenci a
tu by neměl překračovat. Pověřme proto náš objekt pouze sestavením
pozdravu a jeho výpis si zpracujme již mimo, v našem případě v metodě
Main()
. Výhodou takto navrženého objektu je vysoká
univerzálnost a znovupoužitelnost. Objekt doposud umí jen psát do konzole,
my ho však přizpůsobíme tak, aby daná metoda text pouze vracela a aby bylo
na jeho příjemci, jak s ním naloží. Takto můžeme pozdravy ukládat do
souborů, psát na webové stránky nebo dále zpracovávat.
Jelikož chceme, aby metoda vracela hodnotu, a sice string
,
změníme její dosavadní typ void
na string
. K
návratu hodnoty použijeme příkaz return
.
Return metodu ukončí a navrátí hodnotu. Jakýkoli kód v těle metody po
return
se již neprovede! Upravme obě třídy:
Metoda Pozdrav()
v Zdravic.cs
:
public string Pozdrav(string jmeno) { return String.Format("{0} {1}", text, jmeno); }
Tělo metody Main()
v Program.cs
:
{CSHARP_CONSOLE} Zdravic zdravic = new Zdravic(); zdravic.text = "Ahoj uživateli"; Console.WriteLine(zdravic.Pozdrav("Karel")); Console.WriteLine(zdravic.Pozdrav("Petr")); zdravic.text = "Vítám tě tu programátore"; Console.WriteLine(zdravic.Pozdrav("Richard")); Console.ReadKey(); {/CSHARP_CONSOLE}
{CSHARP_OOP} class Zdravic { public string text; public string Pozdrav(string jmeno) { return String.Format("{0} {1}", text, jmeno); } } {/CSHARP_OOP}
Nyní je náš kód napsaný dle dobrých praktik. Naši třídu ještě
okomentujme, jak se sluší a patří. Komentáře budeme psát nad název
třídy a nad název každého atributu a metody. K jejich zápisu použijeme
trojlomítko ///
, VS nám poté vygeneruje XML, do kterého vše
popíšeme. Vyplatí se nám to ve chvíli, kdy na třídě používáme
nějakou metodu. Její popis se nám poté zobrazí v našeptávači. Pokud by
nám komentáře v kódu vadily (zabírají přece jen několik řádek),
můžeme je sklapnout pomocí malých tlačítek "-"
.
Zdokumentovaná třída může vypadat např. takto:
/// <summary> /// Třída reprezentuje zdravič, který slouží ke zdravení uživatelů /// </summary> class Zdravic { /// <summary> /// Text pozdravu /// </summary> public string text; /// <summary> /// Pozdraví uživatele textem pozdravu a jeho jménem /// </summary> /// <param name="jmeno">Jméno uživatele</param> /// <returns>Text s pozdravem</returns> public string Pozdrav(string jmeno) { return String.Format("{0} {1}", text, jmeno); } }
Vidíme, že nám VS popisky opravdu zobrazí:
A jsme u konce. Námi napsaný program má již nějakou úroveň, i když vlastně nic nedělá. Za úkol máte předělat si naši konzolovou kalkulačku do objektů.
V následujícím cvičení, Řešené úlohy k 1.-2. lekci OOP v C# .NET, si procvičí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 2169x (24.81 kB)
Aplikace je včetně zdrojových kódů v jazyce C#