Programování

Rozhraní v Javě

Rozhraní Java se liší od tříd a je důležité vědět, jak používat jejich speciální vlastnosti ve vašich programech Java. Tento kurz představuje rozdíl mezi třídami a rozhraními a poté vás provede příklady, které ukazují, jak deklarovat, implementovat a rozšířit rozhraní Java.

Dozvíte se také, jak se rozhraní vyvinulo v prostředí Java 8 s přidáním výchozích a statických metod a v prostředí Java 9 s novými soukromými metodami. Díky těmto doplňkům jsou rozhraní užitečnější pro zkušené vývojáře. Bohužel také stírají hranice mezi třídami a rozhraními, takže programování rozhraní je pro začátečníky Java ještě více matoucí.

stáhnout Získat kód Stáhněte si zdrojový kód například pro aplikace v tomto výukovém programu. Vytvořil Jeff Friesen pro JavaWorld.

Co je to rozhraní Java?

An rozhraní je bod, kde se dva systémy setkávají a interagují. Můžete například použít rozhraní prodejního automatu k výběru položky, zaplatit za ni a obdržet jídlo nebo pití. Z hlediska programování je rozhraní umístěno mezi softwarovými komponentami. Zvažte, že rozhraní hlavičky metody (název metody, seznam parametrů atd.) Leží mezi externím kódem, který volá metodu, a kódem v rámci metody, která bude provedena jako výsledek volání. Zde je příklad:

System.out.println (průměr (10, 15)); double average (double x, double y) // rozhraní mezi průměrným (10, 15) hovorem a návratem (x + y) / 2; {návrat (x + y) / 2; }

Pro začátečníky v jazyce Java je často matoucí, že třídy mají také rozhraní. Jak jsem vysvětlil v Javě 101: Třídy a objekty v Javě, rozhraní je část třídy, která je přístupná kódu umístěnému mimo ni. Rozhraní třídy se skládá z nějaké kombinace metod, polí, konstruktorů a dalších entit. Zvažte výpis 1.

Výpis 1. Třída účtu a její rozhraní

třída Účet {soukromý název řetězce; soukromá dlouhá částka; Účet (název řetězce, dlouhá částka) {this.name = name; setAmount (částka); } neplatný vklad (dlouhá částka) {this.amount + = částka; } Řetězec getName () {návratové jméno; } long getAmount () {vrácená částka; } void setAmount (dlouhé množství) {this.amount = amount; }}

The Účet (název řetězce, dlouhá částka) konstruktér a neplatný vklad (dlouhá částka), Řetězec getName (), long getAmount (), a void setAmount (dlouhé množství) metody tvoří Účet rozhraní třídy: jsou přístupné externímu kódu. The soukromé jméno řetězce; a soukromá dlouhá částka; pole jsou nepřístupná.

Více informací o rozhraních Java

Co můžete dělat s rozhraními ve vašich programech Java? Získejte přehled s Jeffovými šesti rolemi rozhraní Java.

Kód metody, který podporuje rozhraní metody, a ta část třídy, která podporuje rozhraní třídy (například soukromá pole), se nazývá metoda nebo třída implementace. Implementace by měla být skrytá před externím kódem, aby mohla být změněna tak, aby splňovala vyvíjející se požadavky.

Když jsou implementace vystaveny, mohou nastat vzájemné závislosti mezi softwarovými komponentami. Například kód metody se může spoléhat na externí proměnné a uživatelé třídy se mohou stát závislými na polích, která měla být skrytá. Tento spojka může vést k problémům, když se implementace musí vyvíjet (možná je třeba odstranit exponovaná pole).

Vývojáři prostředí Java tedy používají funkci jazykového rozhraní k abstraktním třídním rozhraním oddělení třídy od svých uživatelů. Zaměřením na rozhraní Java namísto tříd můžete minimalizovat počet odkazů na názvy tříd ve zdrojovém kódu. To usnadňuje přechod z jedné třídy do druhé (možná kvůli zlepšení výkonu), jak váš software dozrává. Zde je příklad:

Názvy seznamu = nový ArrayList () void print (Názvy seznamu) {// ...}

Tento příklad deklaruje a inicializuje a jména pole, které obsahuje seznam názvů řetězců. Příklad také deklaruje a tisk() metoda pro tisk obsahu seznamu řetězců, možná jeden řetězec na řádek. Pro stručnost jsem vynechal implementaci metody.

Seznam je rozhraní Java, které popisuje sekvenční kolekci objektů. ArrayList je třída, která popisuje implementaci pole založenou na poli Seznam Rozhraní Java. Nová instance ArrayList třída je získána a přiřazena Seznam proměnná jména. (Seznam a ArrayList jsou uloženy v knihovnách standardních tříd java.util balík.)

Úhlové závorky a generika

Úhlové závorky (< a >) jsou součástí sady obecných funkcí Java. Naznačují to jména popisuje seznam řetězců (v seznamu lze uložit pouze řetězce). Obecná představím v budoucím článku Java 101.

Při interakci s kódem klienta jména, vyvolá ty metody, které jsou deklarovány Seznam, a které jsou implementovány ArrayList. Kód klienta nebude přímo komunikovat s ArrayList. Výsledkem je, že se kód klienta nerozbije, když se použije jiná třída implementace, například Spojový seznam, je požadováno:

Názvy seznamu = nový LinkedList () // ... neplatný tisk (názvy seznamu) {// ...}

Protože tisk() typ parametru metody je Seznam, implementace této metody se nemusí měnit. Pokud by však ten typ byl ArrayList, typ by musel být změněn na Spojový seznam. Pokud by obě třídy deklarovaly své vlastní jedinečné metody, možná budete muset výrazně změnit tisk()implementace.

Oddělení Seznam z ArrayList a Spojový seznam umožňuje vám psát kód, který je imunní vůči změnám implementace třídy. Pomocí rozhraní Java můžete zabránit problémům, které by mohly vzniknout při spoléhání se na třídy implementace. Toto oddělení je hlavním důvodem pro používání rozhraní Java.

Deklarace rozhraní Java

Deklarujete rozhraní dodržováním syntaxe podobné třídě, která se skládá ze záhlaví následovaného tělem. Záhlaví se skládá minimálně z klíčového slova rozhraní následuje název, který identifikuje rozhraní. Tělo začíná znakem s otevřenou vzpěrou a končí těsnou vzpěrou. Mezi těmito oddělovači jsou deklarace záhlaví konstanty a metody:

rozhraní identifikátor {// tělo rozhraní}

Podle konvence je první písmeno názvu rozhraní velkými písmeny a následující písmena malými písmeny (například Kreslitelné). Pokud se název skládá z více slov, je první písmeno každého slova psáno velkými písmeny (například DrawableAndFillable). Tato konvence pojmenování je známá jako CamelCasing.

Výpis 2 deklaruje rozhraní s názvem Kreslitelné.

Výpis 2. Příklad rozhraní Java

rozhraní Drawable {int RED = 1; int ZELENÁ = 2; int MODRÁ = 3; int ČERNÁ = 4; int BÍLÁ = 5; void draw (int color); }

Rozhraní ve standardní knihovně tříd Java

Jako konvence pojmenování končí mnoho rozhraní ve standardní knihovně tříd jazyka Java znakem schopný přípona. Mezi příklady patří Vyvolatelné, Cloneable, Srovnatelný, Formovatelný, Iterable, Spustitelný, Serializovatelné, a Přenosný. Přípona však není povinná; standardní knihovna tříd obsahuje rozhraní CharSequence, Vlastník schránky, Sbírka, Vykonavatel, Budoucnost, Iterátor, Seznam, Mapa a mnoho dalších.

Kreslitelné deklaruje pět polí, která identifikují barevné konstanty. Toto rozhraní také deklaruje záhlaví pro a kreslit() metoda, která musí být volána s jednou z těchto konstant k určení barvy použité k nakreslení obrysu. (Použití celočíselných konstant není dobrý nápad, protože je možné předat jakoukoli celočíselnou hodnotu kreslit(). Postačují však v jednoduchém příkladu.)

Výchozí nastavení záhlaví pole a metody

Pole, která jsou deklarována v rozhraní, jsou implicitně veřejné konečné statické. Záhlaví metody rozhraní jsou implicitně veřejný abstrakt.

Kreslitelné identifikuje typ odkazu, který určuje, co má dělat (něco nakreslit), ale ne jak to udělat. Podrobnosti implementace jsou přiřazeny třídám, které implementují toto rozhraní. Instance takových tříd se nazývají kreslitelné, protože vědí, jak kreslit samy.

Značkovací a značkovací rozhraní

Rozhraní s prázdným tělem je známé jako značkovací rozhraní nebo a značkovací rozhraní. Rozhraní existuje pouze pro přidružení metadat ke třídě. Například, Cloneable (viz Dědičnost v Javě, část 2) znamená, že instance jeho implementační třídy lze povrchně klonovat. Když Objektje klon () metoda detekuje (pomocí identifikace typu běhového modulu), že třída volající instance implementuje Cloneable, povrchně klonuje objekt.

Implementace rozhraní Java

Třída implementuje rozhraní připojením Java nářadí klíčové slovo následované seznamem názvů rozhraní oddělených čárkami do záhlaví třídy a kódováním každé metody rozhraní ve třídě. Výpis 3 představuje třídu, která implementuje výpisy 2 Kreslitelné rozhraní.

Výpis 3. Kruh implementující rozhraní Drawable

třída Kruhové nářadí Drawable {private double x, y, radius; Kruh (dvojité x, dvojité y, dvojitý poloměr) {this.x = x; this.y = y; this.radius = radius; } @Override public void draw (int color) {System.out.println ("Circle drawn at (" + x + "," + y + "), with radius" + radius + ", and color" + color); } dvojitý getRadius () {návratový poloměr; } double getX () {return x; } dvojnásobek getY () {návrat y; }}

Výpis 3 Kruh třída popisuje kružnici jako střed a poloměr. Kromě poskytnutí konstruktoru a vhodných metod getru, Kruh realizuje Kreslitelné připojením nářadí Drawable do Kruh záhlaví a přepsáním (jak je uvedeno v @ Přepis anotace) Kreslitelnéje kreslit() záhlaví metody.

Výpis 4 představuje druhý příklad: a Obdélník třída, která také implementuje Kreslitelné.

Výpis 4. Implementace rozhraní Drawable v kontextu obdélníku

třída Obdélníkové nářadí Drawable {private double x1, y1, x2, y2; Obdélník (dvojitý x1, dvojitý y1, dvojitý x2, dvojitý y2) {this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; } @Override public void draw (int color) {System.out.println ("Obdélník nakreslený s levým horním rohem v (" + x1 + "," + y1 + ") a pravým dolním rohem v (" + x2 + "," + y2 + ") a barva" + barva); } double getX1 () {return x1; } double getX2 () {return x2; } double getY1 () {návrat y1; } dvojitý getY2 () {návrat y2; }}

Výpis 4 Obdélník třída popisuje obdélník jako dvojici bodů označujících levý horní a pravý dolní roh tohoto tvaru. Stejně jako u Kruh, Obdélník poskytuje konstruktor a vhodné metody getru a také implementuje Kreslitelné rozhraní.

Přepsat záhlaví metody rozhraní

Kompilátor nahlásí chybu při pokusu o kompilaciabstraktní třída, která zahrnuje nářadí klauzule rozhraní, ale nepřepíše všechny hlavičky metod rozhraní.

Datové hodnoty typu rozhraní jsou objekty, jejichž třídy implementují rozhraní a jejichž chování je určeno hlavičkami metody rozhraní. Tato skutečnost znamená, že můžete přiřadit odkaz na objekt proměnné typu rozhraní za předpokladu, že třída objektu implementuje rozhraní. Výpis 5 ukazuje.

Výpis 5. Aliasing Circle and Rectangle objects as Drawables

třída Draw {public static void main (String [] args) {Drawable [] drawables = new Drawable [] {new Circle (10, 20, 15), new Circle (30, 20, 10), new Rectangle (5, 8 , 8, 9)}; for (int i = 0; i <drawables.length; i ++) drawables [i] .draw (Drawable.RED); }}

Protože Kruh a Obdélník nářadí Kreslitelné, Kruh a Obdélník objekty mají Kreslitelné typ kromě svých typů tříd. Proto je legální ukládat odkazy na každý objekt v poli Kreslitelnés. Smyčka iteruje přes toto pole a vyvolá každou Kreslitelné objektu kreslit() metoda kreslení kruhu nebo obdélníku.

Za předpokladu, že je výpis 2 uložen v a Drawable.java zdrojový soubor, který je ve stejném adresáři jako Circle.java, Obdélník.java, a Draw.java zdrojové soubory (které ukládají Výpis 3, Výpis 4 a Výpis 5), kompilujte tyto zdrojové soubory pomocí některého z následujících příkazových řádků:

javac Draw.java javac * .java

Spusťte Kreslit aplikace takto:

java Draw

Měli byste dodržovat následující výstup:

Kruh nakreslený v (10,0, 20,0), s poloměrem 15,0 a barvou 1 Kruh nakreslený v (30,0, 20,0), s poloměrem 10,0 a barvou 1 Obdélník nakreslený s levým horním rohem v (5,0, 8,0) a pravém dolním rohu na (8,0, 9,0) a barva 1

Všimněte si, že stejný výstup můžete také vygenerovat zadáním následujícího hlavní() metoda:

public static void main (String [] args) {Circle c = new Circle (10, 20, 15); c.draw (Drawable.RED); c = nový kruh (30, 20, 10); c.draw (Drawable.RED); Obdélník r = nový Obdélník (5, 8, 8, 9); r.draw (Drawable.RED); }

Jak vidíte, je zdlouhavé opakovaně vyvolávat objekty každého objektu kreslit() metoda. Tímto způsobem navíc přidáte další bytecode do Kreslitsoubor třídy. Myslet na Kruh a Obdélník tak jako Kreslitelnés, můžete využít pole a jednoduchou smyčku ke zjednodušení kódu. Toto je další výhoda z navrhování kódu, který upřednostňuje rozhraní před třídami.

Pozor!

$config[zx-auto] not found$config[zx-overlay] not found