Clase interne și clase înglobate
Clasele pot fi înglobate (nested), adică pot fi definite în interiorul altor clase. Un caz particular al claselor înglobate sunt clasele interne (inner class). De exemplu, avem o clasă Person în interiorul căreia este definită o clasă Account:
public class Program{
public static void main(String[] args) {
Person tom = new Person("Tom", "qwerty");
tom.displayPerson();
tom.account.displayAccount();
}
}
class Person{
private String name;
Account account;
Person(String name, String password){
this.name = name;
account = new Account(password);
}
public void displayPerson(){
System.out.printf("Person \t Name: %s \t Password: %s \n", name, account.password);
}
public class Account{
private String password;
Account(String pass){
this.password = pass;
}
void displayAccount(){
System.out.printf("Account Login: %s \t Password: %s \n", Person.this.name, password);
}
}
}
Clasa internă se comportă ca o clasă obișnuită, cu excepția faptului că obiectele sale pot fi create doar în interiorul clasei externe.
Clasa internă are acces la toate câmpurile clasei externe, inclusiv cele marcate cu modificatorul private. De asemenea, clasa externă are acces la toți membrii clasei interne, inclusiv la câmpuri și metode private.
Referința la obiectul clasei externe dintr-o clasă internă poate fi obținută folosind expresia Clasa_Externă.this, de exemplu, Person.this.
Obiectele claselor interne pot fi create doar în clasa în care sunt definite. În alte clase externe, nu se pot crea obiecte ale clasei interne.
O altă caracteristică a claselor interne este că acestea pot fi declarate în orice context, inclusiv în interiorul unei metode sau chiar într-un ciclu:
public class Program{
public static void main(String[] args) {
Person tom = new Person("Tom");
tom.setAccount("qwerty");
}
}
class Person{
private String name;
Person(String name){
this.name = name;
}
public void setAccount(String password){
class Account{
void display(){
System.out.printf("Account Login: %s \t Password: %s \n", name, password);
}
}
Account account = new Account();
account.display();
}
}
Clase înglobate statice
Pe lângă clasele interne, pot exista și clase înglobate statice. Clasele înglobate statice permit ascunderea unor informații complexe în interiorul clasei externe:
class Math{
public static class Factorial{
private int result;
private int key;
public Factorial(int number, int x){
result = number;
key = x;
}
public int getResult(){
return result;
}
public int getKey(){
return key;
}
}
public static Factorial getFactorial(int x){
int result = 1;
for (int i = 1; i <= x; i++){
result *= i;
}
return new Factorial(result, x);
}
}
Aici, este definită o clasă înglobată pentru stocarea datelor despre calculul factorialului. Operațiile principale sunt efectuate de metoda getFactorial, care returnează un obiect al clasei înglobate. Acum putem folosi aceste clase în metoda main:
public static void main(String[] args) {
Math.Factorial fact = Math.getFactorial(6);
System.out.printf("Factorialul numărului %d este %d \n", fact.getKey(), fact.getResult());
}
În acest exemplu, clasa Factorial stochează rezultatul calculului factorial și numărul pentru care s-a făcut calculul, iar metoda statică getFactorial returnează un obiect al acestei clase.