Pouze tento týden sleva až 80 % na e-learning týkající se Javy. Zároveň využij akce až 50 % zdarma při nákupu e-learningu - více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.
java week + discount 50

Lekce 2 - První objektová aplikace v C# - Hello object world

Minulá lekce, Úvod do objektově orientovaného programování v C#, nás uvedla do objektově orientovaného programování.

Již víme, že objekty mají atributy a metody. Také víme, že k vytvoření objektu vytvoříme nejprve třídu. Ta je vzorem, podle které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!

Založme si ve Visual Studiu novou konzolovou aplikaci tak, jak jsme to dělali doposud. V Solution Exploreru napravo klikneme pravým tlačítkem myši na náš projekt a vybereme Add -> Class. Jde to i klávesouvou zkratkou Shift + Alt + C.

Přidání nové třídy class k C# projektu ve Visual Studio

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 první. Název je samozřejmě také bez diakritiky, tu v programu používáme max. uvnitř textových řetězců, nikoli v identifikátorech.

Vytvoření nové třídy v C# ve Visual Studio

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 našem případě vám to může přijít zbytečné, u složitějších aplikací si to budete 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 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 ji mít ve stejném jmenném prostoru. To zde platí, VS samo novou třídu obalí tím samým jmenným prostorem, vy místo HelloObjects budete mít název své aplikace, pokud jste 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, Linq a Text. Pro nás bude nejdůležitější namespace System, protože právě ten obsahuje třídu Console. Další využijeme až později a poté budeme dokonce potřebovat nějaké 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á.

Všimněte 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(), 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, C# by ji chápal jako private (neveřejná). Metoda nebude vracet žádnou hodnotu, toho docílíme klíčovým slovem void. Dále bude následovat samotný název metody, metody píšeme stejně jako třídy velbloudí notací s velkým poč. 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, jen 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 do naší proměnné.

Při vytvoření nové instance se zavolá tzv. konstruktor. To je speciální metoda na třídě, proto při vytvoření instance píšeme ty 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). My jsme v kódu žádný konstruktor nedeklarovali, C# si proto vytvořil tzv. implicitní bezparametrický konstruktor. Vytvoření instance objektu je tedy podobné 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, a není ještě 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ě:

            Zdravic zdravic = new Zdravic();
            zdravic.Pozdrav();
            Console.ReadKey();
    class Zdravic
    {

        public void Pozdrav()
        {
            Console.WriteLine("Hello object world!");
        }

    }

Program spustíme.

Vaš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. Upravíme nyní naši metodu Main():

            Zdravic zdravic = new Zdravic();
            zdravic.Pozdrav("Karel");
            zdravic.Pozdrav("Petr");
            Console.ReadKey();
    class Zdravic
    {

        public void Pozdrav(string jmeno)
        {
            Console.WriteLine("Ahoj uživateli {0}", jmeno);
        }

    }

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 2x 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 ně 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í musíme pochopitelně nastavit vytvořené instanci v Program.cs:

            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();
    class Zdravic
    {
        public string text;

        public void Pozdrav(string jmeno)
        {
            Console.WriteLine("{0} {1}", text, jmeno);
        }

    }

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 si každý objekt ovlivňoval vstup a výstup, jak se mu zachce. Pochopitelně narážím 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 náš objekt pouze sestavením pozdravu a jeho výpis si zpracujeme 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 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 to 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:

            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();
    class Zdravic
    {
        public string text;

        public string Pozdrav(string jmeno)
        {
            return String.Format("{0} {1}", text, jmeno);
        }
    }

Nyní je náš kód dle dobrých praktik. Ještě naši třídu 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 zobrazí v našeptávači. Pokud by nám komentáře v kódu vadily (zabírají přeci 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);
    }

}

Podíváme se, že nám VS opravdu popisky zobrazí:

Metody objektu zdravic ve Visual Studio

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 1930x (24.81 kB)
Aplikace je včetně zdrojových kódů v jazyce C#

 

Předchozí článek
Úvod do objektově orientovaného programování v C#
Všechny články v sekci
Objektově orientované programování v C# .NET
Přeskočit článek
(nedoporučujeme)
Řešené úlohy k 1.-2. lekci OOP v C# .NET
Článek pro vás napsal David Čápka
Avatar
Uživatelské hodnocení:
279 hlasů
David je zakladatelem ITnetwork a programování se profesionálně věnuje 13 let. Má rád Nirvanu, sushi a svobodu podnikání.
Unicorn university David se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity

 

 

Komentáře
Zobrazit starší komentáře (185)

Avatar
Alesh
Překladatel
Avatar
Alesh:6. května 23:51

Však na konzultaci u kamaráda není nic špatného, klidně to s ním prober. ;-)
V podstatě jde o toto:
Ta původní kalkulačka je prostě jen kód nablitý do Main. Předělání do objektové podoby vlastně znamená to, že uděláš třídu Kalkulacka a v Main vytvoříš její instanci. Pak to může vypadat třeba tak, že kalkulačka bude mít metodu Spustit, ta ti vypíše takové to Vítej atd., vyzve k zadání čísel a operace. Posbíráš ty vstupy dovnitř objektu kalkulačky, zpracuje je, a nakonec ti vypíše výsledek. Můžeš udělat i ten dotaz, zda pokračovat dalším zadáním.
Prostě jde o to, že tu kalkulačku uděláš jako ten objekt, se kterým komunikuješ z toho hlavního programu. Čili nejdřív ji vytvoříš, ona ti něco vypíše, ty ji něco zadáš, ona něco spočítá, zeptá se, zda chceš zadat další. Je to jasnější?
Hele, já byl z toho taky zmatenej v této fázi výuky, ale až dojdeš dál, tak to pochopíš. Klidně se na tu kalkulačky v tuto chvíli vyprdni, pak se k ní třeba vrátíš, až se ti to v hlavě pospojuje, jak to vlastně funguje, resp. má fungovat. ;-)

 
Odpovědět
6. května 23:51
Avatar
Jan Prokop
Člen
Avatar
Odpovídá na Alesh
Jan Prokop:7. května 0:01

Ahoj, Aleši, díky za koment. Konzultace je za mne samozřejmě ideální stav a nebyla by první ani poslední, akorát mě to občas zdržuje od dalšího postupu. Tady naštěstí pomohlo jít zatím dál a hned v Praktickém cvičení na prvním příkladu jsem pochopil, co by se dalo s Kalkulačkou udělat.:) Baví mne to čím dál víc, jak se postupně zorientovávám.

 
Odpovědět
7. května 0:01
Avatar
Vašek Slunčík:10. května 23:48

Nepodařilo se mi podle textu zprovonit ani Zdraviče. VS hlásil, že Zdravič je mimo kontext. Musel jsem ručně doplnit - omluvte laický popis - všechna using a namespace. Na jednu stran mám radost, že jsem na to ke zdárnému výsledku přišel, na druhé straně ale mám pocit, že to jen nějak patlám a nechápu podstatu ovládání VS.

Odpovědět
10. května 23:48
Já na to přijdu!
Avatar
Vašek Slunčík:11. května 0:24

Jako jo, je to zbytečné volání metod, když vše by šlo udělat v jednom switchi, ale zkusil jsem si to zobecnit jak jen to šlo. Trochu vždy bojuji s tím co kde mít. Má kalkulačka jen počítat? Nebo i zobrazit text? Má řešit vstupy? Nebo to bude dělat jiný objekt?
Je to mé první programování objektů v C#, trochu jsem večer nadával, ale k půlnoci to dal a hrál si s tím :)

PROGRAM

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ObjektovaKalkulacka;

    class Program
    {
        static void Main(string[] args)
        {
            Vstup vstup = new Vstup();
            Kalkulacka kalkulacka = new Kalkulacka();

            bool pokracovat = true;

            while (pokracovat)
            {
                int a = vstup.ZadejHodnotu("a", -999, 999);
                int b = vstup.ZadejHodnotu("b", -999, 999);
                int operace = vstup.ZadejHodnotu(kalkulacka.text, kalkulacka.operaceMin, kalkulacka.operaceMax);

                double vysledek = kalkulacka.Spocti(a, b, operace);
                Console.WriteLine("{0} {1} {2} = {3}", a, kalkulacka.vyraz, b, vysledek);

                if (vstup.ZadejHodnotu("Přeješ si pokračovat? 1 - ano, 2 ne", 1, 2) == 2)
                    pokracovat = false;
            }
        }
    }

VSTUP

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ObjektovaKalkulacka
{
    internal class Vstup
    {
        public int ZadejHodnotu(string nazevPrvku, int min, int max)
        {
            string text = String.Format("Zadej {0}:", nazevPrvku);
            int zadanaHodnota = 0;
            bool zadaniOK = false;
            Console.WriteLine(text);

            while (!zadaniOK)
            {
                while (!int.TryParse(Console.ReadLine(), out zadanaHodnota))
                    Console.WriteLine("Chybné zadání, zkus znovu. " + text);

                if (zadanaHodnota >= min && zadanaHodnota <= max)
                    zadaniOK = true;
                else
                    Console.WriteLine("Zadání mimo rozsah {0} - {1}, zkus znovu. " + text, min, max);

            }
            return zadanaHodnota;
        }
    }
}
KALKULACKA
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ObjektovaKalkulacka;

internal class Kalkulacka
{
    public string text = "Vyber operaci: 1 - sečíst, 2 - odečíst, 3 - násobit, 4 dělit";
    public int operaceMin = 1;
    public int operaceMax = 4;
    public string vyraz = "";

    public double Spocti(int a, int b, int operace)
    {
        double vysledek = 0;
        switch(operace)
        {
            case 1:
                vysledek = this.Secist(a, b);
                break;
            case 2:
                vysledek = this.Odecist(a, b);
                break;
            case 3:
                vysledek = this.Nasobit(a, b);
                break;
            case 4:
                vysledek = this.Delit(a, b);
                break;
            default:
                // náhoda v budoucnu je blbec
                break;
        }
        return vysledek;
    }

    private double Secist(int a, int b)
    {
        vyraz = "+";
        return a + b;
    }

    private double Odecist(int a, int b)
    {
        vyraz = "-";
        return a - b;
    }

    private double Nasobit(int a, int b)
    {
        vyraz = "x";
        return a * b;
    }

    private double Delit(int a, int b)
    {
        double c = 0;
        vyraz = "nelze dělit";
        if (b != 0)
        {
            vyraz = "/";
            double aa = a;
            c = aa / b;
        }

        return c;
    }
}
Odpovědět
11. května 0:24
Já na to přijdu!
Avatar
Pavel Rössner:10. června 21:50

Musel jsem si text přečíst opakovaně a plně jsem ho pochopil až po pročtení několika následujících lekcí. Lekce je jinak pěkná, ale pro úplné začátečníky by místy potřebovala detailnější vysvětlení.

 
Odpovědět
10. června 21:50
Avatar
Antonín Pohl:9. července 14:41

Tak přispěju taky svým prvním OOP výtvorem :)
CALCULATOR:

namespace Kalkulacka_s_while
{
    internal class Calculator
    {
        public float a;
        public float b;
        public string Pokracovat;
        public void Pozdrav()
        {
            Console.WriteLine("Vítejte v kalkulačce!");
        }
        public void ZadejCisla()
        {
            Console.WriteLine("Zadej první číslo:");
            float a = float.Parse(Console.ReadLine());
            Console.WriteLine("Zadej druhé číslo:");
            float b = float.Parse(Console.ReadLine());
        }
        public void ZvolOperaci()
        {
            Console.WriteLine("Zvol si operaci:");
        }
        public void Scitani()
        {
            Console.WriteLine("Součet: {0}", a + b);
        }
        public void Odcitani()
        {
            Console.WriteLine("Rozdíl: {0}", a - b);
        }
        public void Nasobeni()
        {
            Console.WriteLine("Součin: {0}", a * b);
        }
        public void Deleni()
        {
            Console.WriteLine("Podíl: {0}", a / b);
        }
        public void Podekuj()
        {
            Console.WriteLine("Děkuji za použití kalkulačky!");
        }
    }
}

PROGRAM:

namespace Kalkulacka_s_while
{
    class Program
    {
        static void Main(string[] args)
        {

            Calculator calculator = new Calculator();
            calculator.Pozdrav();
            calculator.Pokracovat = "ano";
            while (calculator.Pokracovat == "ano")
            {
                Console.WriteLine("Zadej první číslo:");
                calculator.a = float.Parse(Console.ReadLine());
                Console.WriteLine("Zadej druhé číslo:");
                calculator.b = float.Parse(Console.ReadLine());
                calculator.ZvolOperaci();
                Console.WriteLine("1 - sčítání");
                Console.WriteLine("2 - odčítání");
                Console.WriteLine("3 - násobení");
                Console.WriteLine("4 - dělení");
                int volba = int.Parse(Console.ReadLine());
                if (volba == 1)
                    calculator.Scitani();
                if (volba == 2)
                    calculator.Odcitani();
                if (volba == 3)
                    calculator.Nasobeni();
                if (volba == 4)
                    calculator.Deleni();
                Console.WriteLine("Přejete si pokračovat? ano/ne");
                calculator.Pokracovat = Console.ReadLine();
             }
            calculator.Podekuj();
            Console.ReadKey();
        }
    }
}

Za jakoukoliv zpětnou vazbu budu rád :)

Odpovědět
9. července 14:41
Každý problém má řešení.
Avatar
Martin Dlabač:21. července 23:15

Chtělo by to přidat do textu vysvětlení, proč musíme přidat "using HelloObjects;". Proč musíme explicitně deklarovat, že má třída použít sama sebe?

 
Odpovědět
21. července 23:15
Avatar
Jaroslav Drobek:1. srpna 17:46

Hodnocení:

  • "Založme si ve Visual Studiu novou konzolovou aplikaci.." - stálo by za to hned doplnit "..s názvem HelloObjects".
  • V komentovaném postupu chybí zmínka o tom, že je třeba zařídit, aby rovněž hlavní třída (class Program) byla umístěna do stejného jmenného prostoru (tj. HelloObjects), případně tento jmenný prostor měla přístupný (using HelloObjects; - viz předchozí komentář Martin Dlabač ).
 
Odpovědět
1. srpna 17:46
Avatar
Zdeněk Brokeš:16. srpna 17:12

Pripadne mi trochu nestastne pri vyuce pouzit hned stejny nazev pro tridu i pro objekt (pouze s rozdilnost velikost pismene). Uz proto ze stejne jak trida se vzdyy jmenuje i konstruktor. Stava se to neprehledne

 
Odpovědět
16. srpna 17:12
Avatar
Marek Němec
Člen
Avatar
Marek Němec:27. srpna 17:24

Ahoj chtěl bych se zeptat zda je rozdíl mezi:

return String.Format("{0} {1}, text, jmeno");

a

return string.Format("{0} {1}, text, jmeno");

Děkuji za přečtení.

Editováno 27. srpna 17:24
 
Odpovědět
27. srpna 17:24
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 10 zpráv z 195. Zobrazit vše