Interface (programová konstrukce)
Rozhraní a implementace
Rozhraní entity je souhrn informací (signatura[1] a kontrakt[2]), kterým entita specifikuje, co o ní okolí ví a jakým způsobem je možné s ní komunikovat. Pojem rozhraní je mimo objektové programování zastoupen v mnoha oborech, rozhraním může být i například uživatelské rozhraní (stroje, programu). Pokud řídíme auto, rozhraním mezi námi a mechanismem otáčejícím koly auta je (pro nás uživatelsky přívětivý) volant. V objektově orientovaném programování rozumíme rozhraním právě takovou specifikaci dané entity, která nám prozrazuje, co uzná za vhodné, aby o ní okolí vědělo – jak s ní mohou okolní entity jednat a jak na takové jednání entita bude reagovat.
Rozhraní nemá nic společného s implementací – můžeme mít auto, které bude mít volant (rozhraní), ale bude mít kola se špatným vzorkem. Přítomností rozhraní (volantu) sice budeme moci otáčet koly auta, ale to, jak auto pojede, nebude závislé na stavu volantu, nýbrž na stavu kol. Jinými slovy, rozhraní nic nedělá, jenom slibuje, co můžeme od dané entity očekávat. Způsob, jakým naše očekávání daná entita splní, nazýváme implementací. (Pecinovský, 2010)
Interface v jazyce Java
V programovacím jazyce Java je zavedena speciální konstrukce – interface. S pomocí této konstrukce je možné definovat rozhraní objektu bez jakékoliv implementace. Deklarace interface se skládá z modifikátoru(ů), klíčového slova interface, jeho názvu, případných rodičovských interface a těla interface. Příklad :
public interface IPriklad extends IRodic1, IRodic2 {
// deklarace konstant
int cislo = 1000;
// deklarace abstraktnich metod
void prvniMetoda (int i, double x);
int druhaMetoda(String s);
}
Modifikátory přístupu (public, private, protected) fungují stejně jako u ostatních objektů. Interface taktéž podporuje dědičnost, avšak, na rozdíl od tříd může interface dědit od několika interface zároveň. Interface je překládán a stejně jako ostatní třídy má po překladu svůj .class soubor.
Tělo interface obsahuje deklarace abstraktních metod (abstraktní proto, že neobsahují žádnou implementaci, místo jejich těla je zde pouze středník), které jsou veřejné, a protože interface konkrétní (implementované) a neveřejné metody mít nemůže, dovoluje syntaxe modifikátory abstract a public vynechat. Tělo může také obsahovat deklarace konstant, které jsou implicitně veřejné, statické a neměnné (final).
(Oracle)
Implementace rozhraní třídou
public class Priklad implements IPriklad{
/* implementovane metody deklarovane v interface
* s prazdnymi tely, resp. s vyjimkou upozornujici na to, ze
* metoda neni (prozatim) podporovana
*/
@Override
public void prvniMetoda(int i, double x) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int druhaMetoda(String s) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
Interface deklaruje pouze abstraktní metody bez implementace, tu musí zajistit třídy, které se k implementaci přihlásí.
K implementaci daného rozhraní se třída přihlašuje veřejně ve své hlavičce (klíčovým slovem implements). Překladač poté kontroluje naplnění tohoto prohlášení, které je zároveň součástí signatury třídy. Tyto třídy se mohou pak vydávat za instance daného interface (interface totiž nemůže mít žádné instance, metody v něm jsou pouze abstraktní, bez implementace).
Třída může implementovat několik rozhraní současně, její instance se pak mohou vydávat za instance kteréhokoliv z těchto interface. Potřebujeme-li kdekoliv v programu instanci interface, musí být zastoupena právě instancí některé ze tříd, které interface implementují. Tato skutečnost odlišuje používání interface od dědičnosti.
Při dědění přebírá třída od rodiče (stejně jako od interface) jeho rozhraní, ale s ním (na rozdíl od interface) i rodičovský podobjekt. Používání interface napomáhá skrýt implementaci a plní tak jednu ze zásad OOP – zapouzdření.
(Pecinovský, 2009)
Výhody používání interface
Interface umožňuje specifikovat zobecnitelné vlastnosti skupiny tříd a definovat metody, které budou moci pracovat s kteroukoliv z instancí dané skupiny.
Pokud je v programu třída nebo skupina objektů, které často podléhají úpravám nebo u kterých v budoucnu hrozí riziko změny, použitím interface jako komunikačního prostředníka mezi takovými objekty a okolím lze snadno zajistit chod programu i navzdory takovýmto změnám. Příkladem takovýchto změn může být rozhodnutí o změně nebo rozšíření podporovaných databázových systémů.
Při počátcích vývoje a návrhu aplikací umožňuje zavedení interface developerům v týmu rychleji definovat interakce mezi jednotlivými objekty navrhovaného programu, aniž by se v rané fázi vývoje museli soustředit na implementaci.
Developeři se tak poté mohou soustředit na dílčí fragmenty vývoje s jistotou, že na jejich budoucí integraci je již brán ohled.
Nové třídy implementující definovaná rozhraní mohou být přidávány do existujícího systému bez významných zásahů do kódu.
Programování proti rozhraní
Používání rozhraní vedlo ke vzniku programovacímu stylu – programování proti rozhraní. Podstata této myšlenky tkví v zavádění programového jádra více na rozhraních objektů, než na jednotlivých implementačních detailech. Programování proti rozhraní snižuje závislost na implementaci a dělá tak kód více znovu-použitelný, tvůrce programu může později měnit chování programu, tak že zamění stávající objekt za nový, který však implementuje stejné rozhraní.
Příklady interface
Java obsahuje mnoho předdefinovaných a často používaných rozhraní:
java.awt.LayoutManager – sloužící k uspořádání grafických objektů na ploše okna.
java.io.DataInput, java.io.DataOutput – tato rozhraní definují metody požadované, pokud objekt chce komunikovat pomocí proudů pro předávání primitivních datových typů nebo znakových dat.
java.lang.Runnable – toto rozhraní definuje metodu run, jejíž kód běží jako samostatné vlákno
java.lang.Comparable– má metodu compareTo, kterou lze popsat rovnost či nerovnost dvou objektů, nebo zda je jeden větší nebo menší než druhý.
Interface v ostatních jazycích
V ostatních objektově orientovaných jazycích se také objevují konstrukty identické či podobné interface v Javě.
Programovací jazyky s přímou podporou interface jsou například: Ada, C#, D, Dart, Delphi, Logtalk, Object Pascal, Objective-C, PHP, Racket, Swift.
příklad Interface v jazyce C#
Ukázka interface v jazyce C# a třídy, která jej implementuje.
public interface IPriklad {
void PrvniMetoda();
}
class Priklad : IPriklad {
public void PrvniMetoda() {
Console.WriteLine("Provádím metodu - PrvniMetoda.");
Console.ReadLine();
}
public static void Main(string[] args) {
Console.WriteLine("Provádím hlavní metodu.");
Priklad p = new Priklad();
p.PrvniMetoda();
}
}
Na příkladu je zřejmé, že se syntaxe v jazyce C# s jazykem Java v mnoha ohledech shoduje.
V jazyce C# je stejně jako v Javě možné, aby interface dědil od více rodičovských interface. Třída, která pak implementuje takovýto interface, musí obsahovat implementace všech metod (jak v daném interface, tak i v jeho rodičích).
Reference
Citovaná literatura
- Oracle. Defining an Interface. The Java Tutorials. [Online] [Cited: 11 30, 2012.] http://docs.oracle.com/javase/tutorial/java/IandI/interfaceDef.html.
- Pecinovský, Rudolf. 2009. Objektově orientované programování? Co to je? Počítač ve škole. [Online] 2009. http://www.pocitacveskole.cz/system/files/uzivatel/9/clanky/pecinovsky_pdf_16661.pdf.
- —. 2010. OOP - Naučte se myslet a programovat objektově. Brno : Computer Press, a.s., 2010. ISBN 978-80-251-2126-9.