Jak programovací jazyk Java, tak i programovací jazyk C# jsou jedny z nejznámějších a nejpoužívanějších jazyků současné doby. A přesto že oba vychází z programovacího jazyka C++ a díky tomu obsahují spoustu stejných prvků, pořád obsahují velké množství prvků, ve kterých se liší a které by měli programátoři znát, pokud již jeden z těchto jazyků umí a rozhodují se, že by se naučili ten druhý. Tento dokument by měl připravit tyto lidi na přechod z jednoho programovacího jazyka do druhého a vysvětlit hlavní rozdíly, které mezi nimi existují.
Tématem této práce je seznámit čtenáře s rozdíly mezi programovacími jazyky Java, konkrétně ve verzi Standard Edition (JavaSE) 8, vydaným společností Oracle Corporation a C# verze 6.0 vydaným společnostní Microsoft Corporation. Porovnat je mezi sebou a rozebrat rozdíly, které vznikají z mnoha různých důvodu, které začínají tím, že každý z jazyků funguje na jiné platformě a pokračují přes nejrůznější konvence až například k různým funkčnostem generických datových typů a spoustě dalších rozdílů.
V příloze této práce na CD jsou přiloženy zdrojové kódy textové adventury, vytvořené v prvním semestru bakalářského studia v předmětu 4IT101 – Programování v Javě. Tato aplikace byla následně upravena pro potřeby této práce a převedena včetně potřebných součástí Frameworku adventury do jazyku C#. Tyto kódy jsou také použity jako většina příkladů v této práci.
Hlavními cíli práce bude:
· Rozebrat rozdíly
o V běžných konvencích
o Mezi datovými typy
o Mezi datovými členy
o Mezi generickými datovými typy
o Ve funkcionálním programování
o Mezi operátory
· Předvést na příkladech, jejichž většina je součástí programu přiloženého k této práci
Pro dosažení cíle použiji zejména dokumentace společnosti Oracle Java 8 Language Specification a společnosti Microsoft C# 5.0 Language Specification a s jejich pomocí postupně porovnám oba programovací jazyky, srovnám funkčnost každého z nich a rozdíly v jejich použití následně zobrazím na připojených příkladech. Z těchto příkladů zároveň vytvořím jednu a tu samou aplikaci, kterou naprogramuji v obou jazycích a jejich zdrojové kódy přiložím k tomuto dokumentu.
Přínos práce spočívá zejména v popisu rozdílů, díky kterým se mohou následně ostatní programátoři, kteří už jeden z uvedených jazyků znají, jednoduše učit používat i druhý zmíněný programovací jazyk.
Před napsáním své práce jsem provedl rešerši literatury. Do této rešerše jsem zařadil knihy a dokumenty týkající se programovacích jazyků Java a C# a dále také spoustu internetových článků, popisujících rozdíly a vlastnosti těchto dvou jazyků.
V oblasti týkající se programovacího jazyka Java jsem využil hlavně dokument od společnosti Oracle Java 8 Language specification [2]. Tento dokument přímo od tvůrců Javy velmi detailně popisuje všechny specifikace až do její, v současné době nejnovější verze Java 8 Standard Edition a rozebírá všechny vlastnosti, které může zmíněný programovací jazyk v současné době nabídnout.
Tento dokument jsem doplnil o knihy Ing. Rudolfa Pecinovského, CSc. Java 7 – učebnice objektové architektury pro začátečníky [30] a Java 8 – Úvod do objektové architektury pro mírně pokročilé[31], zabývajícími se výukou objektově orientovaného programování ve výše zmíněném jazyce. Obě knihy výborně popisují základy programování s pomocí objektově orientovaného programování, které se následně z Javy dá, s malými úpravami, použít i v jiných jazycích, jako je například C#.
Dále pro informace o Java Streams API a lambda výrazech jsem využil informací z diplomové práce Maxima Rytycha Možnosti deklarativního programování v jazyku Java 8 [47], zabývající se možnostmi deklarativního programování v jazyce Java 8 s pomocí již zmíněných lambda výrazů a Streams API. A dále také informace z bakalářské práce Jana Sýkory Knihovna umožňující práci s libovolnými zdroji dat prostřednictvím SQL dotazů [48], zabývající se vytvořením knihovny umožňující práci s libovolnými zdroji pomocí SQL příkazů.
V oblasti týkající se programovacího jazyka C# jsem využil především dokument C# Language Specification [1] od společnosti Microsoft Corporation. Tento dokument, podobně jako dokument jazykové specifikace Javy, obsahující většinu informací o předchozí verzi programovacího jazyka C# 5.0 a všechny jeho důležité vlastnosti. Bohužel, tento dokument je nejnovější jazykovou specifikací jazyka C#.
K tomuto jazyku jsem dále využil internetovou příručku pro programování na platformě .NET a konkrétně v jazyce C# od společnosti Microsoft Corporation. Která na svých stránkách Microsoft Developer Network uvádí spoustu velmi zajímavých a snadno pochopitelných příkladů ve dříve zmíněném programovacím jazyce. Na tomto webu se nachází informace o poslední vydané verzi jazyka C# 6.0 a proto jsou zde rozebrány i vlastnosti poslední verze tohoto jazyka.
Při porovnávání jazyků v oblasti generických datových typů, jsem využil článek Miroslava Viriuse Generické programování v C++, Javě a C# z knihy Objekty 2005 [3], ve kterém popisuje rozdíly mezi implementací generických datových typů tří výše zmíněných programovacích jazyků a také výborný článek Jonatana Pryora Porovnání generických datových typů v Javě a C# [24], který porovnává implementaci generických datových typů mezi programovacími jazyky probíranými v této práci.
Následně při tvorbě praktického projektu jsem využil knihu ing. Pecinovského OOP a Java 8: Návrh a vývoj složitějšího projektu vyhovujícího zadanému rámci [52]. Tato kniha popisuje tvorbu tohoto projektu na vytvořeném rámci a učí začínající programátory stylům objektově orientovaného programování pomocí mnoha zajímavých informací a příkladů.
Historie[1] Javy začíná na začátku 90. let minulého století, kdy malá skupina inženýrů firmy Sun Microsystems nazývaná Green Team, vedená Jamesem Goslingem vytvořila nový programovací jazyk, který měl provést revoluci ve světě. Tímto jazykem byla Java.
Prvním výrobkem, který Green Team vytvořil, bylo interaktivní kapesní zařízení používané pro domácí zábavu, na kterém prezentovali svůj procesorově nezávislý programovací jazyk. Avšak společnosti o toto zařízení nejevily zájem. V té chvíli se skupina se svým projektem začleňuje zpět do Sun Microsystems a mění svoje zaměření ze set-top boxů na online služby, CD-ROMy a desktopové platformy.
V roce 1997[2] se Java s téměř 400 000 vývojáři stává druhým nejpoužívanějším programovacím jazykem na světě. O dva roky později předefinovala firma Sun Microsystems architekturu Java platformy a představila Java 2 platformu ve třech různých variantách. Java 2 Standard Edition (J2SE) pro desktopy a pracovní stanice, Java 2 Enterprise Edition (J2EE) pro složité serverové systémy a Java 2 Micro Edition (J2ME) pro uživatelská zařízení. Tímto velmi zjednodušila programátorům, poskytovatelům služeb a výrobcům zařízení možnost, zaměřit se na vybrané segmenty trhu.
Za pět let od té doby co jazyk Java vznikl, se stihl vyvinout z nástroje pro animování webových stránek do plnohodnotného programovacího jazyka, který se dá použít prakticky všude od čipových karet, přes bankomaty, mobilní telefony a počítačové hry až ke složitému desktopovému a serverovému softwaru. V roce 2000 se na vývojářské konferenci JavaOne připojil na jevišti ke generálnímu řediteli společnosti Sun Microsystems spoluzakladatel a ředitel společnosti Apple Steve Jobs a prohlásil, že Apple připojí Javu ke každé verzi jejich operačního systému Mac OS X. Následující rok na té samé konferenci pronesla společnost Sony Computer Entertainment svou záminku integrovat platformu Java do své konzole PlayStation 2 a dovolit tak uživatelům stahování nových aplikací a služeb dynamicky a bezpečně z prostředí internetu.
V roce 2004 vznikla na konferenci JavaOne velká debata o tom, zda by se měla Java začít vydávat jako open source[3] řešení. V současné době totiž Sun vyžadoval, aby byly všechny projekty, které byly stavěny na platformě Java, certifikovány jako kompatibilní se specifikací Javy. A všechny změny v jazyce Java musely projít procedurami Java Community Process (JCP)[4] což je mechanismus pro vývoj standardních technických specifikací pro technologii Javy. Během tohoto jednání odsouhlasili open source model pro Javu zástupci společností IBM a Apache Software Foundation, zatímco člen společnosti Sun a tvůrce Javy James Gosling, spolu s viceprezidentem společnosti Sun Robem Gingellem a analytikem společnosti Red Monk se stavěli proti. Gosslink svůj postoj obhajoval tím, že povolení více open source implementací Javy by vedlo k nekompatibilitě, podobně jako například u Unixu a později také u různých distribucí Linuxu.
Navzdory tomu však v roce 2006 společnost Sun uvolňuje Javu jako open-source projekt. Java je od tohoto roku dostupná pod licencí GNU General Public Licence[5], stejné, která je použita například k vývoji OS Linux. Sun tímto nabízí zdarma všechny tři platformy Javy pod GPL licencí.
V roce 2007 byla na konferenci JavaOne ohlášena JavaFX - nové technologické produkty designované ke zjednodušení stavby webových sítí a Java aplikací podporujících rozsáhlou škálu zařízení. A rok na to se Java dostává na další média, konkrétně Blu-ray disky.
V následujícím roce, tedy v roce 2009 je oznámeno odkoupení firmy Sun společností Oracle. Je to oznámeno na další konferenci JavaOne, kde společně vystoupili předseda firmy Sun Scot McNealy a CEO společnosti Oracle Larry Ellison, který oznámil, že Java je pro ně velice atraktivní platforma a přímo řekl, že „Middleware společnosti Oracle je postaven 100% na Javě.“
Další vývoj standardů Javy je následně schvalován pomocí výkonné komise JCP a implementace open-source je přesunuta na projekt OpenJDK.[6] Následující plán, zahrnující zpětnou vazbu od komunity a schvalování pomocí výkonné komise JCP vede ke standardizaci technologií v Javě 7 pro platformu JavaSE, vydané v roce 2011. Zároveň s touto verzí Javy vydává Oracle vývojové prostřední NetBeans verze 7.2, které má plnou podporu JavaFX 2.2. Toto prostředí také dále podporuje jiné programovací jazyky jako například JavaScript, Groovy, C++ a PHP.
O dva roky později vychází Java 7 také pro platformu JavaEE a s sebou přináší mnohé vymoženosti, jako jsou například snížení času odpovědi díky používání obousměrné komunikace pomocí WebSocketů[7], schopných navázat interaktivní komunikaci mezi serverem a webovým prohlížečem, zjednodušení parsování dat s využitím JSONu a podpora asynchronních RESTových webových služeb.
Poslední velká změna v jazyce Java přišla v roce 2014, kdy se světu představila nová verze Javy s označením Java 8. Tato verze přinesla nejen nové programové funkce jako například zakomponování lambda výrazů, nebo nové možnosti paralelního programování pomocí Streams API, ale také s sebou přivedla novou verzi JavyFX, pod podobným označením JavaFX 8. K této nové verzi společnost Oracle vydala novou verzi jejich vývojového prostředí NetBeans, také ve verzi 8.0.
Během vývoje[8] .NET Frameworku byly knihovny s třídami psány pomocí kompilátoru spravovaného kódu (Managed code compiler system) nazývaného Simple Managed C (SMC). V lednu 1999 pak Anders Hejlsberg sestavil tým, pro vytvoření nového programovacího jazyka, v té době nazývaného Cool (což byla zkratka pro C-like Object Oriented Language). Cool byl také název, který Microsoft pro svůj nový programovací jazyk zvažoval, jenže kvůli ochranným známkám následně svoji volbu přehodnotil a tak vznikl název C#. Do tohoto jazyku byly následně po veřejném oznámení projektu .NET v červenci roku 2000 portovány knihovny a rozhraní ASP.NET.
Přední návrhář a hlavní architekt C# Anders Hejlsberg, který byl v minulosti zapojen do návrhu jazyků Turbo Pascal, Embarcadero Delphi (dříve CodeGear Delphi a Borland Delphi) a Visual J++, uvedl ve spoustě interview a technických dokumentech, že právě chyby v mnoha jiných programovacích jazycích (např. C++, Java, Delphi nebo Smalltalk) pomohly vytvořit základy k CLR, který na oplátku vytvořil základy jazyka C#.
Našli se však i tací, jako byl například tvůrce Javy James Gosling, který spolu se spoluzakladatelem Sun Microsystems Billem Joyem tvrdili, že C# není nic jiného než jen imitací Javy. Gosling dokonce prohlásil že „C# je pouze Java postrádající spolehlivost, produktivitu a bezpečnost.“ Dále také Klaus Kreft a Angelika Lagner (tvůrci knihy o datovodech (angl. streams) v jazyce C++), vydali v příspěvek, ve kterém zmiňují že „Java a C# jsou skoro identické programovací jazyky. Pouze se nudně opakují a ztrácí inovaci.“ Anders Hejlsberk však na tyto narážky tvrdí že C# v žádném případě není klonem Javy a je ve svém designu dokonce více podobný jazyku C++ než Javě.
Od vydání verze C# 2.0 v roce 2005 své tvrzení také začíná dokazovat. Jak Java tak C# se v té době začaly hodně vyvíjet, každý z nich si však zvolil jinou cestu a začali se odlišovat. Jedna z velkých odlišností přišla při přidání generických datových typů do obou jazyků, kde každý z nich zvolil jiný způsob jejich implementace. Dále C# pokračoval v přidávání dalších funkcí podporujících funkcionální programování, které nakonec vyvrcholilo ve vydání sady funkcí s názvem LINQ, která byla vydána spolu s verzi C# 3.0. Spolu s touto knihovnou přijal C# spoustu nových funkcí jako například lambda výrazy,[9] které podporují psaní anonymních funkcí, delegátů nebo stromů výrazů.
Následně vydal Microsoft v roce 2010 C# ve verzi 4.0[10], kde představil datový typ dynamic, pojmenování parametrů, dobrovolné parametry a kovarianci a kontravarianci pro generické a delegátové datové typy. Následující verze C# 5.0[11] vyšla v roce 2012 a přinesla obrovskou změnu pro asynchronní programování. Konkrétně se jednalo o možnost psaní asynchronního kódu mnohem jednodušeji a přehledně, skoro stejným způsobem jako synchronní programování. K novému způsobu asynchronního programování přidal Microsoft také dvě nová klíčová slova, async a await.
Zatím poslední verzí jazyka C# byla verze 6.0[12], která byla vydána spolu s poslední verzí vývojového prostředí Visual Studio 2015. Zároveň s touto verzí byl vydán také nový .NET kompilátor, který je nyní vydáván jako open-source a dostal název Roslyn. Novinkami v této verzi jazyka jsou například Getter-Only Auto Properties, neboli vlastnosti, ve kterých není nutné definovat privátní členy pro jednoduché situace jako get, a set a dále možnost tyto vlastnosti rovnou také inicializovat.
public Bag Instance {get;} = new Bag();
V příkladu je ukázána veřejná instance jedináčka (singleton) Bag, která má veřejný pouze getter a zároveň rovnou přiřazenou novou instanci třídy Bag. Dále se velmi zjednodušila kontrola proměnných, zda nejsou null.
public int OnChanged(string name)
{
ChangeListener?.Invoke(name);
}
Operátor ? dokáže zjistit, zda je možné ChangeListener zavolat a následně spustí požadovanou funkci. Další změnou jsou statické členy, kdy máme možnost zbavit se vypisování třídy před statickými členy použitím using static ClassName. Následně můžeme místo ClassName.Value volat pouze Value. Další novinkou v C# verze 6.0 je tzv. Interpolace stringových typů (String Interpolation), která nám velice zjednodušuje formátování stringů. Není nutné používat funkci String.Format a kryptické parametry {0},{1}…, ale k vrácení textu se jménem a příjmením nám stačí pouze znak dolaru a názvy proměnných, jak je ukázáno na příkladu pod tímto odstavcem.
public override string ToString()
{
return $"Name: {Name}, Surname: {Surname}";
}
A díky další novince v této verzi C# nazvané Expression-Bodied Method je možné tuto funkci napsat pomocí lambda výrazu pouze na jeden řádek.
public override string ToString() => $"Name: {Name}, Surname: {Surname}";
Dalšími změnami v této verzi jsou například operátor nameof, který vrátí název daného členu a proto není nutné jej psát ručně, podmíněné výjimky, kdy je možné zadat podmínku, za které bude výjimka odchycena, použití await i v catch blocích a možnost zjednodušit inicializaci indexovaných prvků, kdy je již není nutné inicializovat jeden po druhém, ale může být použit kód podobný jako v následující ukázce.
var result = new Dictionary<string, int>()
{
["A"] => 1,
["B"] => 2
}
Tímto způsobem může programátor nastavit vícero klíčů a hodnot přímo při inicializaci instance třídy Dictionary.
[1] History of Java Technology. Oracle.com [online]. [cit. 2016-03-06]. Dostupné z: http://www.oracle.com/technetwork/java/javase/overview/javahistory-index-198355.html
[2] Java Timeline. Oracle.com [online]. [cit. 2016-03-11]. Dostupné z: http://oracle.com.edgesuite.net/timeline/java/
[3] What is open source. Opensource.com [online]. [cit. 2016-03-11]. Dostupné z: https://opensource.com/resources/what-open-source
[4] The Java Community Process(SM) Program. The Java Community Process [online]. [cit. 2016-03-11]. Dostupné z: https://www.jcp.org/en/home/index
[5] Licences - GNU Project. The GNU Operating System and the Free Software Management [online]. [cit. 2016-03-11]. Dostupné z: http://www.gnu.org/licenses/licenses.html#GPL
[6] OpenJDK. Openjdk.java.com [online]. [cit. 2016-03-11]. Dostupné z: http://openjdk.java.net/
[7] WebSockets - Web APIs. Mozilla Developer Network [online]. [cit. 2016-03-11]. Dostupné z: https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API
[8] History of C# Programming. All About C# Programming [online]. [cit. 2016-03-13]. Dostupné z: http://aboutcsharpprogramming.blogspot.cz/2012/09/history-of-c-programming.html
[9] Výrazy Lambda. Microsoft Developer Network [online]. [cit. 2016-03-13]. Dostupné z: https://msdn.microsoft.com/cs-cz/library/bb397687.aspx
[10] C# 4.0 new features. ZetCode, tutorials for programmers [online]. [cit. 2016-03-30]. Dostupné z: http://zetcode.com/lang/csharp/csharp4/
[11] New features added to C# 5.0. DotNet Tricks [online]. [cit. 2016-03-30]. Dostupné z: http://www.dotnet-tricks.com/Tutorial/csharp/TaH9171113-New-features-added-to-C
[12] Co je nového v C# 6.0. Czech MSDN Blog [online]. [cit. 2016-03-30]. Dostupné z: https://blogs.msdn.microsoft.com/vyvojari/2015/05/11/co-je-novho-v-c-6-0/
Každý ze zde probíraných programovacích jazyků funguje nativně na jiné platformě (Java na Platformě Java a C# na Platformě .NET a z toho se také odvíjí řada jejich rozdílných vlastností.
Platformy Java a .NET, na rozdíl od hardwarově založených platforem, jako jsou například již zmíněný Microsoft Windows, Linux nebo Mac OS jsou pouze softwarové platformy, které mohou být spouštěny nad výše zmíněnými platformami.
Obrázek 1 – Schéma kompilace zdrojového kódu Javy
Platforma Java se skládá ze dvou součástí. První je virtuální stroj Javy (angl. Java Virtual Machine (JVM)), na jehož instanci se aplikace napsané v Javě nebo jiných jazycích pro Platformu Java spouští, a tou druhou je rozhraní pro programování aplikací v jazyce Java, neboli Java API (Application Programming Interface). Toto API je kolekce již předpřipravených komponent, které jsou následně sdruženy do jednotlivých knihoven a poskytují spoustu užitečných funkcí při programování v jazyce Java.
V programovacím jazyce Java je všechen zdrojový kód psán do textových souborů s koncovkou java. Tyto soubory jsou následně zkompilovány pomocí javac kompilátoru do souborů s koncovkou class. Tyto soubory však ještě neobsahují procesorem čitelný nativní kód, namísto toho obsahují tzv. bytekód, jazyk pro virtuální stroj Javy, který tento kód dokáže přečíst a spustit.
Vzhledem k tomu, že Java je platformě závislé prostředí, může být pomalejší než programovací jazyky kompilované přímo do nativního kódu. Ovšem dnešní technologie a hardwarové možnosti současných počítačů dělají tyto rozdíly, pokud se nejedná o software s vysokými hardwarovými nároky, téměř nepostřehnutelné.
Obrázek 2 – Schéma kompilace zdrojového kódu pro platformu .NET
Každý z programů napsaných v C# funguje na .NET Frameworku[1]. Komponentě Microsoft Windows, která obsahuje virtuální spouštěcí systém nazývaný Common Language Runtime (CLR) a jednotnou sadu knihoven. CLR je komerční implementace Common Language Interface stvořená Microsoftem. Common Language Interface (CLI) je mezinárodní standard pro vytváření spouštěcích a vývojových prostředí.
Zdrojový kód napsaný v jazyce C# je tedy zkompilován do tzv. Intermediate Language (IL), který odpovídá specifikacím CLI. Tento kód, společně s ostatními zdroji jako obrázky a texty, je následně na PC ukládán v archivu s příponami například .exe nebo .dll. Pokud se jedná aplikace pro jiná zařízení, jako jsou například mobilní telefony, přípony mohou být různé. Například .appx pro Windows Store aplikace. Archiv v sobě také ještě obsahuje soubor s informacemi (tzv. manifest), který obsahuje informace o typu sestavení, verzi a bezpečnostní požadavky.
Následně při spuštění je tento soubor načten do CLR a to se poté, díky informacím v něm uloženým, správně nastaví. Po správném nastavení, pokud je to možné, provede CLR Just-In-Time kompilaci[2], která následně převede potřebné části kódu v IL do počítačových instrukcí. Díky Just-In-Time kompilaci, nemusí CLR převádět celý program, jako to dělají AOT, neboli Ahead-Of-Time kompilátory, které převedou všechen kód ještě předtím, než je program spuštěn, ale převádí pouze kód, který je potřeba k současnému používání programu. Podobný způsob Just-In-Time kompilace[3] využívá i Java Virtual Machine pro kompilaci kódu uloženého v class souborech.
[1] https://msdn.microsoft.com/en-us/library/z1zx9t92.aspx#Anchor_1
[2] Understanding .NET Just-In-Time Compilation. Telerik [online]. [cit. 2016-03-13]. Dostupné z: http://www.telerik.com/blogs/understanding-net-just-in-time-compilation
[3] Understanding Just-In-Time Compilation and Optimalization. Oracle.com [online]. [cit. 2016-03-13]. Dostupné z: http://docs.oracle.com/cd/E15289_01/doc.40/e15058/underst_jit.htm
Oba jazyky mají své standardy pro psaní kódu a jmenné konvence, která se sice dodržovat nemusí, ale programátoři jsou na ně zvyklí. Tyto konvence budou následně použitý v příkladech pro tuto práci, a proto zde budou nejprve probrány.
Oba jazyky mají různé konvence při pojmenovávání tříd, metod i proměnných, tyto rozdíly zde budou následně probrány.
Balíčky v Javě[1] by měly být pojmenovávány pouze malými písmeny a v případě, že by mělo být víceslovné, měla by tato slova následovat přímo za sebou bez jakéhokoliv oddělovacího znaménka. Balíčku, obsahujícímu základní třídy by měl předcházet určitý prefix. Mělo by se jednat například o kód země, následovaný názvem společnosti. V případě společnosti „Company“, sídlící v České republice, by prefix mohl být například cz.company.
Naproti tomu jmenné prostory v C#[2], by měly pro pojmenovávání používat Pascalovu notaci (Pascal case). Což je způsob pojmenování, který doporučuje začít pojmenování velkým písmenem, následovaným malými písmeny a pokud je v názvu více slov, nebudou se ničím oddělovat, ale každé další slovo bude začínat velkým písmenem. Pokud se to hodí, měl by být název jmenného prostoru napsán v množném čísle. Výjimku v tomto případě tvoří případné zkratky a názvy značek.
C# na rozdíl od Javy doporučuje místo prefixu začínajícím kódem země začít názvem společnosti, za kterým bude následovat název technologie. V případě že bychom tedy měli stejnou společnost „Company“ jako v příkladu výše, vyvíjející technologii Technology, prefix by mohl být Company.Technology.
U obou jazyků se při pojmenovávání datových typů používá Pascalova notace. Oba jazyky také doporučují používat pro názvy tříd podstatné jméno nebo více podstatných jmen a nedoporučuje používání zkratek, pokud nejsou více rozšířeny, než jejich dlouhé formy (jako například URL nebo HTML).
C# ještě doporučuje, že zkratky by se neměly psát velkým písmenem, pokud nejsou dlouhé dva znaky a méně (např. UserID nebo PageHtml). A pokud se to hodí, doporučuje používat název rodičovské třídy u názvů třídy potomků (například ApplicationException je potomkem třídy Exception).
Interfejsy (angl. interface), by stejně jako třídy měly používat Pascalovu notaci, ovšem oba jazyky se shodují na tom, že jejich názvy by měly být přídavná jména, popisující chování třídy. Doporučuje se, aby přídavné jméno v angličtině končilo na able (např. Clonable).
C# k tomu ještě dodává, že každý interfejs[3] by mělo začínat písmenem I, pro okamžité rozeznání, že se jedná o interfejs. Tím se název v Javě Clonable mění na IClonable v C#. Také mu nevadí používat v názvech interfejsů podstatná jména, za předpokladu že popisují chování třídy.
Java doporučuje pro pojmenovávání metod používat hlavně slovesa. Podstatná jména mohou být použita při popisu, co se bude měnit, například pro gettery a settery. Jméno metody by nemělo být dlouhé a mělo by přesně popisovat, co metoda dělá. To znamená, že pokud je metoda delší a dělá více věcí, než název popisuje, měla by být rozdělena na více metod.
Metoda by měla pro pojmenování používat velbloudí notaci (Camel case), která je stejná jako Pascalova notace, s výjimkou toho, že první písmeno je malé. Pro parametry metody se také používá velbloudí notace.
C# s výjimkou toho, že nepoužívá gettery a settery souhlasí s výkladem Javy s jednou změnou. Pro pojmenovávání metod nepoužívá velbloudí, ale Pascalovu notaci.
V Javě se pro pojmenovávání vlastností třídy používá velbloudí notace a jsou definovány jako privátní. Pro jejich přístup se následně používají přístupové metody. Pro názvy metod i jejich parametrů se v Javě používá velbloudí notace.
V C# se pro pojmenovávání vlastností používá Pascalova notace a jsou definovány jako veřejné. Pokud bychom chtěli někomu zabránit v úpravě atributu, nastaví se mu setter jako privátní. Více v kapitole Přístupové metody. Pro názvy metod se používá Pascalova notace a pro názvy jejich parametrů velbloudí notace.
Oba jazyky mají doporučení, podle kterých by se měl jejich kód psát. Některé jsou stejné, některé se liší, ale dalo by se říct, že konvence obou jazyků jsou si hodně podobné. Nejprve zde budou tedy probrány konvence, které jsou pro oba jazyky stejné.
Oba jazyky doporučují, aby se psal pouze jeden příkaz na jednu řádku, stejně tak při deklaraci proměnných, deklarovat jednu na jednom řádku. Dále také doporučují odsazovat kód čtyřmi mezerami, Java dává uživateli na výběr, zda chce odsazovat čtyři mezery, nebo tabulátor o délce čtyř mezer. C# doporučuje použít mezery.
Další doporučení Javy při deklaraci proměnných uvnitř bloků kódu, je deklarovat tyto proměnné přímo za začátkem kódu a nečekat až na první výskyt této proměnné.
Oba jazyky se shodují v tom, že mezi deklaracemi metod by měla být vložena jedna prázdná řádka.
Java také doporučuje vkládat prázdnou řádku mezi deklaraci vlastností třídy a následující metodu.
C#, vzhledem k tomu, že vlastnosti třídy deklaruje jako veřejné a zároveň pro ně deklaruje i getter a setter, doporučuje vkládat prázdné řádky i mezi jednotlivé deklarace vlastností.
Java doporučuje, při deklaraci bloků kódu, jako například u metod, ale také u tříd, podmínek, nebo cyklů umísťovat složené závorky, které označují začátek bloku na stejný řádek, kde se nachází jeho deklarace. Složené závorky označující konec bloku doporučuje vložit na nový řádek. Java také doporučuje použít složené závorky pro označení bloku kódu i při definování podmínek nebo cyklů, které obsahují pouze jeden příkaz.
C# doporučuje při deklaraci bloků kódu umísťovat nejen složenou závorku označující konec bloku ale i tu, která označuje začátek bloku na samostatný řádek, pod deklaraci tohoto bloku.
[1] Java Naming Standards and Programming Conventions. IWombat.com [online]. [cit. 2016-04-21]. Dostupné z: http://www.iwombat.com/standards/JavaStyleGuide.html
[2] Namespace Naming Guidelines. Microsoft Developer Network [online]. [cit. 2016-04-21]. Dostupné z: https://msdn.microsoft.com/en-us/library/893ke618%28v=vs.71%29.aspx
[3] Interface Naming Guidelines. Microsoft Developer Network [online]. [cit. 2016-04-21]. Dostupné z: https://msdn.microsoft.com/en-us/library/8bc1fexb%28v=vs.71%29.aspx
Pro větší přehled při psaní programů, se pro organizaci používají jmenné prostory (angl. namespace) v jazyce C# a balíčky (angl. package) v jazyce Java. Obě dvě organizační jednotky slouží hlavně ke zlepšení přehledu organizační struktury, pro následné uložení a lepší práci s vytvořenými třídami programu.
Pro obě jednotky platí určitá pravidla. Jako například že všechny datové typy jako třídy, interfejsy, výčtové typy atd. musí mít v každém balíčku nebo jmenném prostoru různé názvy. Je tedy možné mít dva jmenné prostory, například s názvy Xharo03Hartman a GameTxt a v každém z nich mít vytvořený interfejs IAuthor. Ovšem není možné mít interfejs IAuthor vytvořený dvakrát v balíčku, nebo jmenném prostoru GameTxt.
namespace Xharo03Hartman
{
interface IAuthor
{
}
}
namespace GameTxt
{
interface IAuthor
{
}
}
Pokud je použita definice, která je vytvořena výše, kompilace proběhne v pořádku, protože každý interfejs s názvem IAuthor má svůj v tomto případě jmenný prostor, do kterého patří a interfejsy na sebe vzájemně nevidí. Kdyby však byly interfejsy v jednom jmenném prostoru nebo balíčku, nastala by chyba, protože kompilátor by nebyl schopný zjistit, z jakého interfejsu následující třída dědí.
package xharo03_hartman;
interface IAuthor {
//Kód interfejsu
}
interface IAuthor {
//Kód interfejsu
}
public class ScenarioManager extends AScenarioManager implements IAuthor {
}
Mezi balíčky a jmennými prostory se však vyskytuje také několik rozdílů. Balíčky, na rozdíl od jmenných prostorů slouží pouze jako organizátor souborů a proto na sebe nenavazují. Mohlo by proto dojít k omylu myslet si, že pokud bychom měli balíčky eu a eu.pedu je mezi nimi nějaký vztah. To nikoliv, balíček eu.pedu je pouze balíčkem s jiným názvem a nemá žádný vztah k balíčku eu.
Na rozdíl od toho jmenné soubory mají své místo působení, každý jmenný prostor má své tělo, které je odděleno složenými závorkami a v tomto místě platí působnost onoho balíčku. Po ukončení složených závorek a těla jmenného prostoru, je možné deklarovat nový jmenný prostor s jiným názvem. Díky tomuto je možné také jmenné prostory na sebe navazovat a proto je ve jmenném prostoru možné, kromě typů vypsaných výše, deklarovat také nový jmenný prostor.
//První jmenný prostor
namespace TestUtil
{
//Jmenný prostor v jiném jmenném prostoru
namespace Common
{
}
}
//Další jmenný prostor
namespace Utilities
{
}
Tento kód je možné zapsat do jednoho souboru a následná kompilace tohoto souboru projde bez chyby.
Dalším rozdílem mezi Javou a C# je používání jmenných prostorů a balíčků v dalším kódu programu. Jak třídy Javy, tak i třídy C# mohou vidět na třídy, nacházející se ve stejném balíčku a jmenném prostoru, ve kterém byly definovány ony. Při použití tříd, které se ve stejném balíčku, či jmenném prostoru nenachází, je potřeba tuto třídu nejprve nadefinovat. Při definování třídy z jiného balíčku se na ni v obou jazycích můžeme odkázat buď celým názvem včetně jejích balíčků:
eu.pedu.adv16s.bp.xharo03_hartman.Main;
Nebo ji nejprve naimportovat v Javě do souboru pomocí klíčového slova import. Pokud importujeme do souboru v jazyce Java, odkazujeme se přímo na třídu, kterou chceme importovat. Pokud bychom chtěli importovat všechny třídy z balíčku, použijeme k tomu znak hvězdy.
//import jedné třídy
import eu.pedu.adv16s.bp.xharo03_hartman.Main;
//import všech tříd z balíčku eu.pedu.adv16s.bp.xharo03_hartman
import eu.pedu.adv16s.bp.xharo03_hartman.*;
Na rozdíl od toho v C# importujeme jmenné prostory pomocí klíčového slova using. Pomocí tohoto slova se importují všechny třídy v uvedeném jmenném prostoru a ty se dají následně použít. Klíčové slovo using se dá použít jak uvnitř jmenného prostoru, tak i vně a následně budou tyto třídy dostupné pro všechny jmenné prostory v současně používaném souboru. C# kromě tohoto nabízí ještě jednu možnost importu pomocí using a to s možností definovat si alias pro určitou třídu a naimportovat pouze tu. Proto, pokud by nějaká třída již importovaná třída, nebo třída v současném jmenném prostoru měla stejný název jako ta, kterou hodláme použít, nemusíme použít její celý název, ale můžeme se na ni odvolat pomocí námi zvoleného aliasu. Alias je samozřejmě možné použít i při importu jmenných prostorů.
//import jmenného prostoru Commands;
using Pedu.Adv16s.BP.Xharo03Hartman.Commands;
//import jmenného prostoru Commands při použití aliasu C
using C = Pedu.Adv16s.BP.Xharo03Hartman.Commands;
//import pouze třídy CommandHelp ze jmenného prostoru Commands jako alias ComH
using ComH = Pedu.Adv16s.BP.Xharo03Hartman.Commands.CommandHelp;
Nyní je možné použít třídu CommandHelp ze jmenného prostoru Commands jako třídu ComH, bez nutnosti se na ni odkazovat celým jejím názvem i pokud bude jmenný prostor obsahovat třídu, se stejným názvem. Pokud by se tato třída měla použít v balíčku Javy, který již tuto třídu obsahuje, bylo by nutné ji volat celým jejím názvem, který by v Javě byl eu.pecu.adv16s.bp.xharo03_hartman.commands.CommandHelp.
Oba programovací jazyky, jak Java, tak C# jsou objektově-orientovanými programovacími jazyky. To znamená, že objekt je základním stavebním prvkem celého programu. Třída je poté základním konstrukčním prvkem v objektově orientovaném programování a slouží jako šablona pro následně objekty, které jsou instancemi oné třídy. V obou případech jak v Javě tak v C# všechny třídy implementují základní třídu Object. Od ní následně dědí všechny další třídy.
C# na rozdíl od Javy přišel s podporou rozdělení jedné třídy do více souborů pomocí klíčového slova partial. Díky tomu je možné vytvořit část třídy, kterou je následně možné doplnit dalšími funkcemi z jiného souboru při vytvoření třídy se stejným jménem včetně jmenného prostoru a klíčového slova partial. Díky tomu je tedy možné doplnit třídy o další prvky a ty následně použít jako rozšíření dané třídy.
namespace Utilities
{
partial class InputForm
{
public void InitializeComponent()
{
...
}
}
}
//Stejná třída v jiném souboru
namespace Utilities
{
partial class InputForm
{
public Field Play()
{
button1_Click(null, null);
}
}
}
Tímto způsobem je možné jednu třídu doplnit o další prvky, jako například ve výše uvedeném příkladu, kde je třída InputForm rozšířena v dalším souboru o funkci Play. C# tento způsob dělení tříd zavedl například kvůli tomu, aby bylo možné při tvoření grafických formulářů oddělit generovaný kód od toho, který píše programátor. Díky tomu se může programátor starat o své věci a mít přehled o tom co píše a všechen vygenerovaný kód je uložen v jiném souboru, do kterého může volně přistupovat, když potřebuje něco změnit.
Oba jazyky povolují vytvoření třídy, od které následně nemůže žádná další třída dědit a není tak možné ji rozšiřovat o její další potomky. V Javě se tyto třídy označují klíčovým slovem final, v C# poté klíčovým slovem sealed.
Dle definice Microsoftu statické třídy[1] (static classes) v C# jsou třídy, u kterých není možné vytvářet jejich instance pomocí klíčového slova new. Není v ní totiž možné vytvářet žádné nestatické členy, všechny vlastnosti a metody, které v ní jsou definovány, jsou definovány jako statické. Tyto třídy mohou být použity jako kolekci pro určitou skupinu metody, které mají něco společného. Příklad této třídy je například třída hry Constants, z balíčku Utils, obsahující texty hry a metodu pro spojování elementů polí typu string.
V C# je implementace statických tříd jednoduchá, při definování třídy se použije klíčové slovo static v přístupových parametrech a kompilátor už se následně postará o to, že ve třídě není možné definovat nestatické členy.
public static class Constants
{
public static string Connect(params string[] strings)
{
//Kód metody
}
}
V Javě existuje jiný postup tvorby statických tříd[2]. Java sama nezavádí pro tyto třídy pojem „statická třída“, spíše používá pojmu utility nebo library class. Pro nadefinování knihovní (library) třídy v Javě je tedy nutné dodržet několik následujících pravidel.
· V deklaraci třídy použít klíčové slovo final, pro znemožnění tvorby potomků statické třídy.
· Konstruktor v této třídě definovat jako privátní, pro zamezení tvorby instancí statické třídy.
· Všechny členy statické třídy definovat jako statické pomocí klíčového slova static. Není možné, aby ve statické třídě byly definovány nestatické členy.
public final class Constants {
private Constants() {
}
public static string connect(String... strings) {
}
}
Před rozebíráním statických konstruktorů je nutné si uvědomit jednu věc a to, že pokud je v objektově orientovaném programování by mělo být objektem úplně všechno všechno. To znamená že je objektem i třída a ta potřebuje ke svému stvoření nějaký konstruktor. Tím je výše zmíněný statický konstruktor.
Statický konstruktor[3] je používán pro inicializace statických dat, nebo provádění akcí, které jsou potřeba provést pouze jednou, před inicializací první instance dané třídy, nebo vytvořením prvních statických členů. Je potřeba si však uvědomit, že statický konstruktor není možné přímo zavolat a proto programátor nemá žádnou kontrolu nad tím, kdy se tento konstruktor spustí.
C# podporuje tvorbu statických konstruktorů, rozdíl mezi klasickým a statickým konstruktorem v C# je pouze ten, že při definování statického konstruktoru se použije klíčové slovo static a žádné přístupové.
public class ACommand
{
static ACommand()
{
new CommandDownload();
...
}
}
Na rozdíl od C#, Java nepoužívá pojmenování statické konstruktory. Místo toho používá statické bloky, nebo také statické inicializátory, kde se do třídy vloží pouze blok kódu ohraničený složenými závorkami, před kterými se deklaruje modifikátor static. Prakticky se ovšem jedná o jedno a to samé, jako statický konstruktor. Pokud by před ním tento modifikátor nebyl, tento kód by byl spuštěn při inicializaci instance.
public class ACommand {
static {
new CommandDownload();
...
}
}
Za další rozdíl by se daly považovat třídy, interfejsy nebo výčtové typy, definované uvnitř jiné třídy nebo interfejsu[4]. Zatímco C# má pouze jeden typ vnořených datových typů, v Javě se tyto typy dělí na nestatické, vnitřní třídy (inner class), a statické, vnořené datové typy (nested types). V předešlé větě je uveden výraz vnitřní třídy, protože pouze třídy mohou být vnitřní, vnořené mohou být i interfejsy a výčtové typy.
Statické datové typy v Javě by se daly porovnat s vnitřními datovými typy, které implementuje C#. Tyto datové typy mají přístup pouze ke statickým typům typu, ve kterém je daný typ definován. A nemají přístup k žádným proměnným existujících instancí tohoto typu. Na druhou stranu ale mohou implementovat statické metody.
// Statická vnitřní třída v Javě
public class Time {
private static class Hour {
}
}
//Její ekvivalent v C#
public class Time
{
private class Hour
{
}
}
Na druhou stranu, nestatický datový typ v Javě nemůže implementovat žádné statické metody, ale na rozdíl od toho má přístup k proměnným instance datového typu, ve kterém se nachází.
Java na rozdíl od C# poskytuje i možnost definovat třídu uvnitř metody. Tato třída je pak použitelná pouze v kontextu oné metody a jinde přístupná není.
class TestClass {
public void classInsideMethod() {
class MethodClass { }
MethodClass mClass = new MethodClass();
}
}
[1] Statické třídy a její členové. Microsoft Developer Network [online]. [cit. 2016-04-18]. Dostupné z: https://msdn.microsoft.com/cs-cz/library/79b3xss3.aspx
[2] Static Classes In Java. Stack Overflow [online]. [cit. 2016-04-18]. Dostupné z: http://stackoverflow.com/questions/7486012/static-classes-in-java
[3] Statické konstruktory (Průvodce programováním v C#). Microsoft Developer Network [online]. [cit. 2016-04-18]. Dostupné z: https://msdn.microsoft.com/cs-cz/library/k9x6w0hc.aspx
[4] C# From a Java Developer Perspective. Dare Obsanjo's Home Page [online]. [cit. 2016-04-07]. Dostupné z: http://www.25hoursaday.com/CsharpVsJava.html#nested
Interfejs (angl. interface) funguje jako kontejner pro definice funkcionalit, který následně mohou třídy implementovat.
Oba jazyky používají interfejsy pro definici seznamu abstraktních metod, které je následně nutné implementovat uvnitř třídy, a tyto třídy se následně mohou vydávat za potomka onoho interfejsu. V obou jazycích mohou třídy dědit z několika interfejsu, ovšem pouze z jedné rodičovské třídy.
public interface INamed {
string getName();
}
Na rozdíl od C#, Java do svých interfejsů dovoluje vkládat také konstanty, statické metody a defaultní metody.
Defaultní metoda je klasická metoda, která v definici obsahuje klíčové slovo default a díky tomu je možné v interfejsu této metodě přiřadit základní funkčnost.
public interface IAuthor {
String getAuthorName();
String getAuthorID();
default String getAuthorString() {
return getAuthorID() + " " + getAuthorName();
}
}
C# na rozdíl od Javy žádné defaultní metody neimplementuje, dle jeho názoru je totiž interfejs pouhým kontejnerem, kde se ukládají abstraktní metody, které musí následně nadefinovat třída, která interfejs implementuje. Ovšem je možné tuto funkcionalitu implementovat pomocí rozšiřujících metod, popsaných v následující kapitole.
Mezi metodami v Javě a C# není moc rozdílů, jedná se spíše o způsob zápisu metod, než velké změny mezi oběma jazyky, ovšem i tyto změny je dobré popsat.
U obou jazyků je známo, že když předáváme nějaké metodě objekt, je do ní předána jeho reference a tuto referenci je možné uvnitř dané metody měnit a následné změny se projeví i vně této metody. Na druhou stranu, pokud do metody vložíme primitivní datový typ, tak pokud ho uvnitř metody změníme, tato změna se neprojeví vně metody a hodnota parametru tedy zůstává stejná, jako byla před odesláním do metody.
C# na tuto vlastnost reaguje klíčovými slovy ref a out[1], v Javě, tato funkčnost ještě nebyla implementována a jediná možnost jak přiřadit novou hodnotu do primitivní proměnné je tedy vytvořit funkci která má určitou návratovou hodnotu a tuto hodnotu následně přiřadit do oné proměnné. Metody s použitím klíčových slov ref a out fungují jiným způsobem.
Pokud má volaná metoda v parametru klíčové slovo ref, místo hodnoty se do ní předá reference na daný primitivní datový typ a změny provedené v této metodě, se následně propíší i do primitivního datového typu, který byl funkci předán.
static void WindowInput()
{
var answer = zUVÍTACÍ_ZPRÁVA;
var command = "";
InputBox.Show(null, answer, ref command);
}
public class InputBox
{
public static void Show(string title, string promptText, ref string value)
{
value = textBox.Text;
}
}
Pokud by volaná metoda obsahovala v parametru místo klíčového slova ref, klíčové slovo out, byla by ignorována jeho výchozí hodnota, která byla do funkce předána. A do primitivní proměnné přidané pomocí tohoto klíčového slova by bylo nutné přiřadit novou hodnotu, která se následně projeví vně této metody v přiřazené proměnné. Před použitím parametru předaného pomocí klíčového slova out je nutné tento parametr v metodě nejdříve inicializovat. Protože nepředává žádnou hodnotu a použití před přiřazením by vyhodilo chybu při kompilaci.
Dalším klíčovým slovem používaným v parametru metody je klíčové slovo params. Pokud máme metodu, která jako parametr obsahuje pole, před kterým se vyskytuje toto klíčové slovo. Je možné do metody zadat libovolné množství arguentů stejného typu jako je ono pole. Všechny tyto argumenty v metodě následně najdeme v parametru, který definovaném jako pole onoho typu s klíčovým slovem params. Jedinou podmínkou je, že tento parametr může být v metodě pouze jednou a musí se nacházet na posledním místě v seznamu parametrů. Jinak by nebylo možné poznat, kde tento parametr končí.
Java také obsahuje stejnou možnost zadávání libovolného počtu argumentů stejného typu do parametru metody, který je metodě předán jako pole. Ovšem zde se toto pole neoznačuje pomocí klíčového slova params, nýbrž pomocí tří teček místo značení pole, což naznačuje, že pole může mít libovolnou velikost. I zde platí, že parametr může být v metodě pouze jednou a na konci metody.
//Metoda s libovolným počtem parametrů v C#
public static string Connect(params string[] strings) { /* Tělo metody */ }
//Ta samá možnost v Javě
public static String connect(String... strings) { /* Tělo metody */ }
Mnoho spustitelných programů (tím jsou myšleny programy, které se dají spustit, samostatné knihovny a frameworky) napsaných v jazycích Java a C# obsahuje jednu spustitelnou metodu. V Javě se tato metoda označuje jako main(String… args), v C# jako Main(string[] args). Tato metoda musí být v obou programovacích jazycích statická, u jazyka Java také veřejná. C# na rozdíl od Javy doporučuje, že jeho metoda Main(string[] args) by veřejná být neměla.
//Metoda main v jazyce Java
class Main {
public static void main(String[] args) {
if((args.length > 0) && ("-text".equalsIgnoreCase(args[0]))){
consoleInput();
}
else{
windowInput();
}
System.exit(0);
}
}
//Metoda main v jazyce C#
static void Main(string[] args)
{
if (args.Length > 0 && args[0] == "-text")
{
ConsoleInput();
}
else if (args.Length > 0 && args[0] == "-old")
{
WindowInputOld();
}
else
{
WindowInput();
}
}
Třída obsahující metodu main/Main nemusí být ani v jednom z jazyků statická a může se dále použít pro vytváření nových instancí. Dalším rozdílem je, že na rozdíl od Javy, může metoda Main v C# obsahovat kromě návratového typu void také typ int.
V obou jazycích může výše zmíněná metoda přijmout nějaké textové parametry, tyto parametry se zadávají jako argumenty programu a oddělují se mezerami. Následně jsou do programu vloženy jako pole textových řetězců.
C# má nastaveno použití tohoto argumentu jako dobrovolné a proto není nutné ho do metody Main psát. Na rozdíl od Javy, ta má sice povinný tento parametry do metody main vložit, ovšem toto pole může být prázdné, takže se před spuštěním programu žádné argumenty stejně vkládat nemusí.
Přebíjení[2] (override) je jazyková vlastnost, která dovoluje v potomkovi přebít metodu své rodičovské třídy. To znamená, že dovolí potomkovi definovat metodu stejného jména, se stejnou návratovou hodnotou, která má stejné typy parametrů definované ve stejném pořadí, jako metoda rodičovská. Je však rozdíl v přebíjení metod v jednotlivých jazycích.
Java má totiž na rozdíl od C# defaultně metody deklarované jako virtuální a pokud u nich není použité klíčové slovo final, které říká, že metoda se nedá dále přebíjet. Je možné je jakkoliv přebíjet v potomcích oné třídy. Při přebíjení metod v Javě se před metodu přidává anotace @Override. Není to nutné, ale je to dobrý zvyk. Pokud tam toto slovo totiž je, kompilátor při kompilaci kódu zkontroluje, jestli opravdu v předkovi existuje ona metoda se stejným názvem, návratovou hodnotou a parametry v zadaném pořadí. Pokud tato metoda neexistuje ne, vyhodí chybu. Pokud by tam anotace @Override nebyla, kompilátor metodu i tak přepíše, ale pokud jsou například špatně napsané parametry, tak to už kompilátor nezjistí a chybu nevyhodí.
V C# je to právě naopak. Metody jsou defaultně považovány za finální a není možné je přebít. Proto by mohlo docházet ke špatnému použití metod, kdy instance potomka použije metodu předka, i když měl použít svou vlastní přebíjející metodu. Tohle se v C# řeší klíčovými slovy virtual a override. V rodičovské třídě se nejprve při definování metody použije klíčové slovo virtual, které říká, že metodu je možné v potomcích dané třídy přebíjet a následně se v definici metody v potomkovi použije klíčové slovo override, které říká, že tato metoda přebíjí virtuální metodu své rodičovské třídy.
public abstract class AFile {
public String execute() {
return Constants.Znespustitelny;
}
public class FilmFile extends AFile {
public String execute() {
return Constants.zSHLEDNUTO;
}
}
public static void Main() {
AFile file = new FilmFile();
file.execute();
}
Po spuštění předchozího zjednodušeného příkladu v Javě by výstup metody execute byl "Právě jste shlédli film. Doufám že se vám líbil :)". Je to kvůli tomu, že i když se navenek instance c tváří jako instance třídy AFile, stále je instancí třídy FilmFile a proto používá její překrytou metodu print.
Pokud by byl ale podobný kód, pouze trochu upravený pro C# spuštěn v C#, výstup by byl "Chyba: Tento soubor nelze spustit.".
Kvůli tomu, že metoda ve třídě AFile neobsahuje klíčové slovo virtual, program neví, že nějaká další metoda existuje. V tomto případě by tedy nešlo o přebíjení ale o zakrývání metod (method hiding). Metoda ve třídě FilmFile pouze zakryla metodu ve třídě AFile, ovšem protože se poslední instance vydává za instanci třídy AFile, třída neví, že třída FilmFile obsahuje metodu, která překrývá metodu třídy AFile a použije tu ze třídy AFile. Pokud by však bylo zakrývání metody použito úmyslně, mělo by se do deklarace metody přidat klíčové slovo new. Pokud tam není, kompilátor vyhodí varování, použití klíčového slova new při zakrývání metody toto varování skryje.
public class FilmFile: AFile
{
public new string Execute()
{
return Constants.zSHLEDNUTO;
}
}
Pokud by měl být výstup v jazyce C# stejný jako v jazyce Java, kód obou tříd by musel vypadat následovně.
public class AFile
{
public virtual string Execute()
{
return Constants.zNESPUSTITELNY;
}
}
public class FilmFile: AFile
{
public override String Execute()
{
return Constants.zSHLEDNUTO;
}
}
V Javě je možné zakrýt pouze statické metody, instanční metody je možné pouze přebít nebo přetížit.
Přetěžování (overloading), na rozdíl od překrývání je vlastnost, která dovoluje programátorům vytvořit dvě metody se stejným názvem ale jinými parametry a tyto metody umístit do stejné třídy.
//C#
public static E GetO<E>(string member, E[] array) where E : struct, INamed
{
return array.First(e =>
{
returne e.GetName()
.Equals(member,StringComparison.CurrentCultureIgnoreCase);
});
}
public static E? GetO<E>(string member, List<E> list) where E : struct, INamed
{
return GetO(member, list.ToArray());
}
//Java
public static <E extends INamed> Optional<E> getO(String member, E[] array) {
return getO(member, Arrays.stream(array));
}
public static <E extends INamed> Optional<E>
getO(String member, Stream<E> stream) {
return stream.filter(iNamed -> iNamed.getName().equalsIgnoreCase(member))
.findAny();
}
Každý objekt může mít definovaný nekonečný počet vlastností a tyto vlastnosti objekty jistým způsobem nastavují (set) a poskytují (get) ostatním objektům kolem sebe. Oba dva zde zmiňované jazyky mají svůj vlastní styl poskytování a nastavování vlastností svých objektů.
Java své vlastnosti v objektech dle zavedených konvencí ukrývá (označuje jako private) a poskytuje je ostatním objektům pomocí přístupových metod. Ty se běžně označují následovně:
· Metody, kterými se vlastnosti v objektech nastavují, běžně začínají slovem set, a proto se nazývají settery.
· Metody, kterými je možné tyto vlastnosti z objektů získat, běžně začínají slovem get, a proto se nazývají gettery.
· Zvláštními typy getterů jsou gettery, které vracejí proměnnou typu boolean, ty poté mohou začínat místo slovem get, slovem is.
Pokud má být poté například zabráněno ostatním objektům tuto vlastnost nastavovat, není nic jednoduššího než nastavit setter vlastnosti jako private, popřípadě ho vůbec neimplementovat.
private Folder currentFolder;
public Field getCurrentPlace() {
return currentFolder;
}
public void setCurrentPlace(Folder folder) {
currentFolder = folder;
}
C# na rozdíl od Javy implementuje gettery a settery svým způsobem. Dle jeho konvencí pokud má být vlastnost třídy přístupná, nastaví se její přístup jako public a poskytne se všem ostatním objektům přímo z instance třídy. Pokud bychom chtěli následně getter a setter vlastnosti nějak změnit, je možné to provést přímo u vlastnosti pomocí klíčových slov get a set a pokud bychom chtěli, aby měla vlastnost například privátní pouze setter, je možné nastavit přístup setteru vlastnosti jako private.
private static Bag _instance;
public static Bag Instance
{
get { return _instance ?? (_instance = new Bag()); }
private set { _instance = value; }
}
Rozšiřující metody (Extension methods) je výborná vlastnost C#, umožňující přidávat do třídy nové metody, bez toho, aniž bychom museli tvořit jejich potomky a bez úprav stávající třídy.
Funguje to tím způsobem, že se ve třídě vytvoří nová statická metoda, které se jako parametr předá odkaz na instanci objektu, se kterým budeme pracovat, kterému předchází klíčové slovo this. Tím zajistíme, že při zavolání metody z instance třídy se tomuto parametru předá právě ta instance třídy, která metodu volá. Následně můžeme s tímto parametrem provádět různé změny, jako by to byla metoda třídy.
Pro použití metody musí být pomocí using importován jmenný prostor, který obsahuje třídu s onou metodou, pokud se třída, ve kterém se používá, nenachází ve stejném jmenném prostoru.
public interface IAuthor
{
string GetAuthorName();
string GetAuthorID();
}
public static class AuthorExtensions
{
public static string GetAuthorString(this IAuthor iAuthor)
{
return iAuthor.GetAuthorID() + " — " + iAuthor.GetAuthorName();
}
}
[1] Main() and Other Methods (C# vs Java). Microsoft Developer Network [online]. [cit. 2016-04-09]. Dostupné z: https://msdn.microsoft.com/en-us/library/ms228506%28v=vs.90%29.aspx
[2] Overriding and overloading in Java and .NET - differences, changes and gotchas. CodeProject [online]. [cit. 2016-04-15]. Dostupné z: http://www.codeproject.com/Articles/692127/Overriding-and-overloading-in-Java-and-NET-differe