Vnoen a vnitn leny mohou bt leny td
Vnořené a vnitřní členy mohou být členy tříd a interfejsů. Je-li X obalem Y a Y je obalem Z, pak Z získá jméno X$Y$Z - kompilací vzniknou classy X, X$Y a X$Y$Z. Z vidí členy všech svých obalů - nehledě na jejich modifikátory přístupu. [ public | protected | private ] [ strictfp ] - [ static ] [ abstract ] interface - vnořený (nested) interfejs - static [ abstract | final ] class - vnořený (nested) třída ---------------- vnitřní interfejsy neexistují [ abstract | final ] class - vnitřní (inner) třída - lokální: bez dalších modifikátorů - anonymní: bez hlavičky Krom anonymní třídy lze uvést extends … resp. implements … • Vnořený člen má přístup jen ke static členům svých obalů. Může mít statické i nestatické členy. I statická třída má konstruktory. • Vnitřní třídy nejsou static a kromě static final konstant nemohou deklarovat žádné statické členy - mohou je však zdědit. PJV 15 1
Vnořené a vnitřní členy tříd a interfejsů Je-li X obalem Y a Y je obalem Z, pak Z získá jméno X$Y$Z - kompilací vzniknou soubory X. class, X$Y. class a X$Y$Z. class. Člen Z vidí členy svých obalů - nehledě na jejich modifikátory přístupu. Má-li však modifikátor static, pak je statickým členem svého obalu – tzv. vnořený ( nested ) - a má přístup jen ke statickým členům svých obalů. Vložit do obalu lze vnořené ( nested ) interfejsy s těmito modifikátory : [ public | protected | private ] [ strictfp ] [ abstract ] [ static ] Vložit do obalu lze třídy s těmito modifikátory : [ public | protected | private ] [ strictfp ] [ abstract | final ] [ static ] Instanciace: In y = new In( ); či Ne n = new Ne( ); // uvnitř Out. Ne n = new Out. Ne( ); // zvnějšku nested Out. In x = new Out( ). new In( ); // zvnějšku inner Tzv. vnitřní ( inner ) třída je nestatickým členem svého obalu. Kromě static final konstant, nemůže deklarovat statické členy – může je však zdědit. Speciálním případem je třída lokální (v metodě) a anonymní (bez hlavičky). PJV 15 2
Lokální třída je vnitřní třída deklarovaná v metodě, bloku či v dynamickém inicializátoru. - jen s modifikátory [ strictfp ] [ abstract | final ] - typ lokální třídy je známý v bloku až za její deklarací. - lze ji instanciovat pouze z vnitřku metody - není přístupná zvnějšku. - k lokálním proměnným a parametrům metody má přístup jen jsou-li finální, neboť nefinální sídlí jen dočasně na zásobníku. - sice return umožňuje objekt vrátit, avšak jeho vlastní typ není vně znám, neb v hlavičce metody nelze zadat jméno lokální třídy jako návratový typ. Lokální třída získá jméno s prefixem ze jmen vnějších tříd a pořadovým číslem metody $n v níž jsou deklarovány stejnojmenné lokální třídy. Tento typ, např. Out$3 Loc, je vně neznámý, tudíž nelze jím přetypovat. Lze užít vně známých typů, které lokální třída rozšiřuje či implementuje. Lokální interfejs není možný - vnitřní interfejsy neexistují. PJV 15 3
Anonymní třída je vnitřní třída bez hlavičky a tudíž: • nemá jméno, modifikátory ani nelze použít extends či implements, • nemůže mít potomky, • nelze definovat žádné její konstruktory, • má jen defaultní konstruktor neznámého jména, • roli konstruktorů event. nahrazují nestatické inicializátory, • instance anonymní třídy má jméno dle obalů ukončené $i, i>=1. TX x = new T(…) {. . . // // T je třída či interfejs TX je T či jeho nadtyp či Object nestatické členy jen statické finální atributy }; PJV 15 4
Adapter je obecně třída, implementující nějaký interfejs tak, že zděděné abstraktní metody přepíše na konkrétní - avšak prázdné. Adapter mívá triviální funkcionalitu a bývá s modifikátorem abstract. Slouží totiž jako předek potomkům, kteří mají některé metody přepsány na neprázdné, čímž získají žádanou funkcionalitu aniž programátor musí psát nepotřebné metody. Např. : interface java. awt. Window. Listener má sedm metod. Adapter definovaný takto: abstract class Window. Adapter implements Window. Listener je všechny metody konkretizuje prázdnými metodami. Ovládat okénko ikonou lze pomocí tzv. handleru, což je objekt vytvořený buď dle normální anebo anonymní třídy. Důležité je, že v obou případech je splněn interfejs Window. Listener. PJV 15 5
Použití adapteru Pojmenovaně: Window. Listener wl = new Window. Handler( ); kde: class Window. Handler extends Window. Adapter { public void Window. Closing( Window. Event ev ) { System. exit(0); // end of application } } či anonymně: Window. Listener wl = new Window. Adapter( ) { public void Window. Closing( Window. Event ev ) { System. exit(0); // end of application } }; PJV 15 6
Inner class Vnitřní třída umožňuje seskupit věcně související kódy a případně je skrýt. public class Outer { private int x; public class Inner { public void m( ) { x++; } } public void test( ) { Inner n = new Inner( ); n. m( ); } public static void main(. . . ) { Outer o = new Outer( ); o. test( ); } } PJV 15 stack heap Inner Outer. this m( this n test( this main( Outer x 7
Inner class public class Outer { private int x; public class Inner { public void m( ) { x++; } } } stack heap Inner Outer. this m( public class Outer. Test { main( public static void main(. . . ) { Outer p = new Outer( ); Outer. Inner n = p. new Inner( ); // n = new Outer( ). new Inner( ); n. m( ); } } this n p Outer x Instanciovat Inner lze jen prostřednictvím instance Outer. PJV 15 8
Inner class public class Outer { private int x; public class Inner { private int x; public void m( int x ) { x++; this. x++; Outer. this. x++; } } } PJV 15 Inner x m( main( Outer. this x n p Outer x 9
Local class public class Outer { private int x = 5; public Object get( final int y ) { final int z = 6; class Local { public String to. String ( ) { return ""+(x+y+z); } } return new Local( ); } public static void main( String [ ] args ) { Outer p = new Outer( ); Object obj = p. get( 700 ); System. out. println( obj ); } // vytiskne 711 } PJV 15 10
Využití vnořených tříd Bod, úsečku, obdélník, elipsu atd. v rovině pojednávají balíčky java. awt s přesností int a java. awt. geom s přesností double a float • abstract class Point 2 D { // nedeklaruje atributy static class Float extends Point 2 D { float x, y; . . . get } static class Double extends Point 2 D { double x, y; . . . get } public double distance( Point 2 D pt ) { return … } public abstract double get. X( ); … // getry a setry } • class Point extends Point 2 D { int x, y; public double get. X( ) {…} … } Od třídy Point 2 D dědí ostatní metody distance, distance. Sq a další. Díky polymorfismu lze: Point 2 D p 1 = new Point 2 D. Double( 1. 1, 2. 2 ); Point p 2 = new Point( 3, 4 ); double d = p 1. distance( p 2 ); PJV 15 11
- Slides: 11