Clase imbricate și clase interioare

În limbajul Java se permite ca o clasă să aibă ca membri alte clase. Acestea se numesc clase imbricate sau clase încuibate (engleza: nested classes). Ca și ceilalți membri, clasele imbricate pot fi statice sau nestatice și se declară în corpul clasei care le încorporează. Clasele imbricate nestatice se numesc clase interioare (engleză: inner classes). O clasă care încorporează (imbrică) alte clase se declară astfel:

    [public] class NumeClasa {
         declaratii_de_membri_ai_clasei
       [modificatori_de_camp] class NumeClasaImbricata {
          declaratii_de_membri_ai_clasei_imbricate
        }
        declaratii_de_membri_ai_clasei
    }

Se recurge la aceasta tehnică atunci când utilizarea unei clase are sens numai în cadrul altei clase. Așadar, prin imbricare se creează o legatură strânsa între două clase. Este posibil, desigur, ca o clasa să conțină mai multe clase imbricate. Remarcăm că declarația clasei imbricate este tratata ca oricare alta declarație de membru al clasei, putând avea și modificatori de câmp (de exemplu static).

Fiind membru al clasei, clasa imbricată are acces la toți membrii clasei care o conține, chiar și la cei privați. Dacă clasa imbricată este statică, ea nu poate referi direct decât membrii statici ai clasei care o conține. Clasa imbricată statică există, la fel ca și câmpurile sau metodele statice, numai în cadrul clasei care o conține, nu și în instanțele acesteia. În consecință, pentru a referi membrii acestei clase, se folosește pentru calificare numele clasei.

Clasa interioară (clasa imbricată nestatică) are câte o instanță în interiorul fiecărei instanțe a clasei care o conține. În consecință, accesul la membrii ei se poate face folosind drept calificator referința la o instanță. Clasa interioară are acces la toți membrii clasei care o conține, atât la cei statici, cât și la cei de instanță (nestatici).
 
Exemplu:

În secțiunea Interfețe a acestui curs, a fost dat un exemplu de aplicație (din fișierul Integrare.java), în care se face integrarea funcțiilor prin metoda trapezelor. În fișierul Integrare.java, toate clasele sunt declarate în mod obișnuit, ca niște clase autonome. În consecință, după compilare se obțin urmatoarele fișiere cu extensia class: Functie1.class, FunctieReala.class, Integrare.class, Integrator.class, IntegrareTrapeze.class.

Clasa IntegrareTrapeze poate fi folosită în diferite aplicații, deci are sens să fie declarată ca o clasa separată. În schimb, clasa Funcție1 este specifica numai unei singure aplicații. Este deci preferabil să fie declarata ca o clasă interioară a acestei aplicații, așa cum se face în fisierul Integrare1.java

Clasa Functie1, din acest exemplu,  a fost declarată ca o clasa interioară (clasă imbricată nestatică) a clasei-aplicație Integrare1. În consecință, accesul la membrii ei se poate face numai printr-o instanță a clasei Integrare1. În acest scop, s-a procedat astfel: 
    a/ s-a creat în metoda main() o instanță a clasei Integrare1 prin instrucțiunea 
    Integrare1 int1=new Integrare1();
    b/ s-a creat o instanță a clasei Functie1 prin instrucțiunea 
    Functie1 f1=int1.new Functie1(arg1,arg2,arg3,arg4);
    c/ Referința f1 la o instanță a clasei interioare f1 a fost apoi utilizată în mod obișnuit, ca argument al metodei integrare()

Atragem atenția asupra modului cum s-a făcut instanțierea clasei interioare Functie1: operatorul  new a fost calificat cu referinta int1 la o instanță a clasei  Integrare1, care o conține. Procedeul de mai sus a fost necesar, întrucat metoda main() este statică, astfel că nu poate accesa direct un membru nestatic al clasei, ci numai prin crearea unei instanțe a acesteia. 

Pentru comparație, în același fișier s-a declarat (tot în clasa-aplicație Integrare1) și o clasa imbricată statică numită Functie2. Remarcăm că instanțierea acesteia s-a făcut în mod "obișnuit" prin instrucțiunea 
    Functie2= func2=new Functie2(arg1,arg2,arg3);
iar utilizarea funcției statice f2() conținute în aceasta s-a facut sub forma "obișnuită"   Functie2.f2(arg1,arg2) . De asemenea, utilizarea funcției nestatice f() a acestei clase s-a făcut "obișnuit", sub forma  func2.f(arg), iar instanța func2 a fost transmisă și ca argument al metodei de integrare. 

După compilarea fișierului Integrare1.java, constatăm că au fost creeate următoarele fișiere cu extensia class: FunctieReala.class, Integrare1.class, Integrare1$Functie1.class, Integrare1$Functie2.class, IntegrareTrapeze.class, Integrator.class. Remarcam ca numele fișieror de bytecode care conțin clase imbricate  sau interioare încep prin numele clasei care le conține, urmat de caracterul $ și de numele clasei imbricate (interioare) respective. În acest fel, devine posibil ca în două aplicații distincte să existe clase imbricate sau interioare cu același nume, fără să se creeze confuzii.



© Copyright 2000 - Severin BUMBARU, Universitatea "Dunărea de Jos" din Galați