Konstruktory v C#
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu
Reklama
Reklama

Konstruktory v C#Konstruktory v C#

 

Konstruktory v C#

Google       Google       8. 4. 2008       52 502×

Určitě jste o nich už slyšeli, možná i víte k čemu jsou a jak fungují. V tomto článku si je ale rozebereme trochu podrobněji.

Reklama
Reklama

Dalo by se říct, že konstruktor je metoda, která se zavolá vždy, když dojde k vytvoření instance třídy nebo struktury. V tomto článku se ale nebudu konstruktory struktur vůbec zabývat (struktura je hodnotový typ, při zavolání implicitního konstruktoru tak vznikne instance s vynulovanými datovými členy). Konstruktor může například nastavovat nějaké výchozí hodnoty, nebo je dostat jako parametr při vytváření instance třídy (pak mluvíme o parametrickém konstruktoru).

Základní konstruktor

public class MojeTřída
{
    public MojeTřída()
    {
        // Toto je tělo konstruktoru.

    }
    // Zbytek třídy bude tady
}

Zatím je to nemastné neslané, máme třídu a v ní konstruktor, který nic nedělá. Jen si všimněte základního poznávacího prvku konstruktoru – musí se jmenovat naprosto stejně jako jeho třída. Jak už bylo několikrát zmíněno, k zavolání konstruktoru dojde při vytvoření instance třídy, tedy například takhle:

MojeTřída třída = new MojeTřída();

Přetěžování konstruktorů

C# podporuje tzv. přetěžování konstruktorů. To znamená, že konstruktorů jedné třídy máme víc, jen s jinými parametry. Naše třída MojeTřída se třemi konstruktory by vypadala takto:

public class MojeTřída
{
    public MojeTřída()
    {
        // Bezparametrický konstruktor

        // První konstruktor

    }

    public MojeTřída(int Věk)
    {
        // Konstruktor s jedním parametrem

        // Druhý konstruktor
    }

    public MojeTřída(int Věk, string Jméno)
    {
        // Konstruktor se dvěma parametry

        // Třetí konstruktor
    }
    // Zbytek třídy bude tady

}

Kompilátor si už sám vybere ten správný konstruktor podle parametrů, které zadáme instanci třídy. Opět si to ukážeme na příkladu.

MojeTřída třída1 = new MojeTřída();
 // Použije se první, bezparametrický konstruktor

MojeTřída třída2 = new MojeTřída(20,"Honza");
// Tentokrát se použije třetí konstruktor
// přijímající dva parametry

MojeTřída třída3 = new MojeTřída("Honza");
// Při pokusu o zkompilování vyhodí chybu - 
// nedefinovali jsme žádný konstruktor, který
// by přijímal jeden parametr typu string

Volání konstruktoru z jiného konstruktoru

C# nám umožňuje zavolat jeden konstruktor z jiného. Řekl bych, že příklad mluví za vše.

public class MojeTřída
{
    public MojeTřída()
        : this(10)
    {
        // Bezparametrický konstruktor

        // Pvní konstruktor

    }

    public MojeTřída(int Věk)
    {
        // Konstruktor s jedním parametrem

        // Druhý konstruktor

    }
}

Trošku blíž si popíšeme tuto část:

public MojeTřída(): this(10)

Klíčové slovo this klasicky odkazuje na třídu, se kterou zrovna pracujeme. Nejinak je tomu tady. Když řekneme this(10), ve skutečnosti tím chceme zavolat metodu public MojeTřída(int Věk). Způsob, který jsme si právě předvedli, se nazývá inicializátor.

Další důležitou věcí je pořadí volání jednotlivých metod (konstruktorů), když využijeme inicializátor. Pokud vytvoříme instanci naší třídy s bezparametrickým konstruktorem, pak se nejdřív zavolá druhý konstruktor (ten s parametrem Věk). V C# nemůžeme explicitně zavolat konstruktor, jako je to možné například u metod, například že bychom napsali MojeTrida(20);. Jediný způsob jak zavolat konstruktor z konstruktoru tak zůstává zmíněná metoda přes inicializátor.

Malá poznámka na závěr: Jediná povolená klíčová slova v inicializátoru jsou this a base (to probereme v další kapitolce).

Konstruktory při dědění

Pro začátek si vytvoříme jednoduchou „třídovou“ konstrukci, ve které vytvoříme dceřinou třídu od třídy MojeBázováTřída.

public class MojeBázováTřída
{
    public MojeBázováTřída()
    {
        // První konstruktor bázové třídy

    }

    public MojeBázováTřída(int Věk)
    {
        // Druhý konstruktor bázové třídy

    }
}

public class MojeZděděnáTřída : MojeBázováTřída
// Zde dochází k dědění
{
    public MojeZděděnáTřída()
    {
        // První konstruktor zděděné třídy

    }

    public MojeZděděnáTřída(int Věk)
        : base(Věk)
    {
        // Druhý konstruktor zděděné třídy

    }
}

Na výše uvedeném kódu není nic k nepochopení, ale jaké bude pořadí volání konstruktorů při vytvoření instance odvozené třídy? Jak mnozí už určitě tušíte, nejdříve se zavolá konstruktor bázové třídy a až po něm konstruktor jejího potomka (tedy odvozené třídy). Z toho tedy vyplývá, že kód konstruktoru bázové třídy se vykoná, i když ho explicitně nezavoláme (což ani nemůžeme) nebo i když nepoužijeme klíčové slovo base. Nelekejte se, to je naprosto normální chování konstruktorů při využití dědičnosti.

Privátní konstruktory

Privátní (soukromé) konstruktory, označené klíčovým slovem private, jsou trochu zvláštní skupinou, proto jim budu věnovat kousek článku. Je to kvůli tomu, že nemůžeme vytvářet instance nebo dědit od třídy, která má pouze privátní konstruktory. K čemu by nám taková třída byla? Téměř k ničemu, snad jen kdybychom ji nacpali statickými členy (opak instančního členu, který je vázán na instanci třídy, statický člen popisuje třídu jako takovou), tudíž bychom nechtěli vytvářet její instance. Můžeme ale mít vedle sebe jak soukromé, tak veřejné konstruktory (public). Vtip je v tom, že veřejný konstruktor se může pomocí nějakého zřetězení dostat do konstruktoru privátního, protože členy označené klíčovým slovem private jsou přeci dostupné zevnitř třídy. Pro lepší pochopení si to znovu ukážeme na příkladu:

public class MojeTřída
{
    private MojeTřída()
    {
        Console.WriteLine("Toto je bezparametrický konstruktor (kl. slovo private!)");
    }

    public MojeTřída(int var)
        : this()
    {
        Console.WriteLine("Toto je konstruktor s jedním parametrem (kl. slovo public)");
    }
}

Pokud uděláme instanci třídy MojeTřída pomocí tohoto kódu:

MojeTřída obj = new MojeTřída(10);

vše bude fungovat jak má, i když se pomocí klíčového slova this odkazuje na privátní konstruktor. Kdybychom ale zkusili vytvořit instanci bez parametru, kompilace by skončila s chybovým hlášením 'Konstruktory.MojeTřída.MojeTřída()' is inaccessible due to its protection level. Tato hláška říká, že náš konstruktor je nepřístupný kvůli jeho přístupovému modifikátoru. Máme tedy před sebou jasný důkaz toho, že privátní členy jsou přístupné jen zevnitř třídy.

Můžeme vytvořit třídu, která bude mít jen privátní konstruktory, ale jak už jsem se zmínil, taková třída nebude děditelná, ani nebudeme moci vytvářet její instance.

To jsme probrali dědění, privátní konstruktory i nějaké obyčejné konstruktory. Co nám ještě zbývá? Dnes se podíváme už jen na statické konstruktory.

Statické konstruktory

Statické konstruktory jsou novinkou až v C# (tím myslím, že nebyly v C++, nevím, jak jsou na tom ostatní jazyky). Zajímavostí tohoto typu konstruktorů je to, že dojde k jeho zavolání ještě před vytvořením první instance třídy. Nemůžeme přesně říct, kdy dojde k zavolání; jediné, co víme jistě, je, že to bude ještě před instancí. Syntaxe je opět velmi jednoduchá, jen přidáme slůvko static.

public class MojeTřída
{
    static MojeTřída()
    {
        // Tělo konstruktoru
        // Může přistupovat jen ke statickým členům!

    }
}

Základní charakteristiky statických konstruktorů si shrneme ve čtyřech bodech:

  1. V jedné třídě může být právě jeden statický konstruktor
  2. Takový konstruktor by měl být bezparametrický.
  3. Může přistupovat pouze ke statickým členům třídy.
  4. V hlavičce statického konstruktoru by neměl být žádný přístupový modifikátor.

Na statických konstruktorech toho mnoho zajímavého už nevykoukáme, takže je čas na nějaký příklad.

public class MojeTřída
{
    static string jméno;
    static MojeTřída()
    {
        jméno = "Honza";
    }
}

Pokud zkusíte přečíst obsah proměnné jméno, klidně i před vytvořením instance třídy, bude v ní uloženo slovo Honza. A to proto, že došlo k zavolání konstruktoru hned, co se procesor dozvěděl, že máme s třídou něco v úmyslu.

FAQ

Na závěr dnešního článku si uvedeme takový krátký FAQ – často kladené otázky.

Co se stane, když nedefinuji žádný konstruktor?

Pokud programátor nedefinuje žádný explicitní konstruktor, kompilátor automaticky použije svůj bezparametrický. Pokud ale definujete třeba jen jeden konstruktor, potlačíte tím toto chování kompilátoru.

Co když budu mít konstruktor pro MojeZděděnáTřída, ale ne pro MojeBázováTřída?

Situace je podobná té výše, aplikace se bez potíží zkompiluje, kompilátor vygeneruje bezparametrický konstruktor pro bázovou třídu.

Může ne-statický konstruktor přistupovat ke statickým členům?

Ano, může, bez jakýchkoliv komplikací. Trošku přísnější jsou statické konstruktory, které mohou přistupovat jen ke statickým členům.

To je pro dnešek vše. Doufám, že vám článek řekl něco nového o světě konstruktorů v jazyce C#.

Zdroj: http://www.codeproject.com/KB/dotnet/ConstructorsInCSharp.aspx

×Odeslání článku na tvůj Kindle

Zadej svůj Kindle e-mail a my ti pošleme článek na tvůj Kindle.
Musíš mít povolený příjem obsahu do svého Kindle z naší e-mailové adresy kindle@programujte.com.

E-mailová adresa (např. novak@kindle.com):

TIP: Pokud chceš dostávat naše články každé ráno do svého Kindle, koukni do sekce Články do Kindle.

Hlasování bylo ukončeno    
0 hlasů
Google
(fotka) Jakub KottnauerJakub studuje informatiku na FIT ČVUT, jeho oblíbenou platformou je .NET.
Web     Twitter     Facebook     LinkedIn    

Nové články

Reklama
Reklama
Obrázek ke článku NEWTON Media prohledá 200  milionů mediálních zpráv během sekund díky Cisco UCS

NEWTON Media prohledá 200 milionů mediálních zpráv během sekund díky Cisco UCS

Česká společnost NEWTON Media provozuje největší archiv mediálních zpráv ve střední a východní Evropě. Mezi její zákazníky patří například ministerstva, evropské instituce nebo komerční firmy z nejrůznějších oborů. NEWTON Media rozesílá svým zákazníkům každý den monitoring médií podle nastavených klíčových slov a nabízí online službu, kde lze vyhledat mediální výstupy v plném znění od roku 1996.

Obrázek ke článku Delphi 10.1.2 (Berlin Update 2) – na co se můžeme těšit

Delphi 10.1.2 (Berlin Update 2) – na co se můžeme těšit

Touto roční dobou, kdy je zem pokrytá barevným listím a prsty křehnou v mrazivých ránech, se obvykle těšíme na zbrusu novou verzi RAD Studia. Letos si však ale budeme muset počkat na Godzillu a Linux až do jara. Vezměme tedy za vděk alespoň updatem 2 a jelikož dle vyjádření pánů z Embarcadero se budou nové věci objevovat průběžně, pojďme se na to tedy podívat.

Obrázek ke článku Konference: Moderní datová centra pro byznys dneška se koná už 24. 11.

Konference: Moderní datová centra pro byznys dneška se koná už 24. 11.

Stále rostoucí zájem o cloudové služby i maximální důraz na pružnost, spolehlivost a bezpečnost IT vedou k výrazným inovacím v datových centrech. V infrastruktuře datových center hraje stále významnější roli software a stále častěji se lze setkat s hybridními přístupy k jejich budování i provozu.

loadingtransparent (function() { var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true; po.src = 'https://apis.google.com/js/plusone.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s); })();
Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032016 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý