CodeGym /Java blog /Véletlen /Névtelen osztályok
John Squirrels
Szint
San Francisco

Névtelen osztályok

Megjelent a csoportban
Szia! A mai órán folytatjuk a beágyazott osztályok témakörének vizsgálatát. Eljött az utolsó csoport ideje: névtelen belső osztályok. Térjünk vissza diagramunkhoz: Névtelen osztályok - 2A helyi osztályokhoz hasonlóan, amelyekről az előző leckében beszéltünk, az anonim osztályok is egyfajta belső osztályok... Több hasonlóság és különbség is van bennük. De először merüljünk el: miért is nevezik őket "névtelennek"? Ennek megválaszolásához vegyünk egy egyszerű példát. Képzeljük el, hogy van egy alapprogramunk, amely folyamatosan fut és csinál valamit. Ehhez a programhoz szeretnénk egy több modulból álló monitoring rendszert létrehozni. Az egyik modul a teljesítmény általános mutatóit követi, és naplót vezet. A második regisztrálja és rögzíti a hibákat egy hibanaplóban. A harmadik a gyanús tevékenységeket követi nyomon: például az illetéktelen hozzáférési kísérleteket és egyéb biztonsággal kapcsolatos dolgokat. Mivel lényegében mindhárom modulnak egyszerűen a program elején kell indulnia és a háttérben futnia,

public interface MonitoringSystem {
  
   public void startMonitoring();
}
3 konkrét osztály fogja megvalósítani:

public class GeneralIndicatorMonitoringModule implements MonitoringSystem {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
}


public class ErrorMonitoringModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor errors!");
   }
}


public class SecurityModule implements MonitoringSystem {

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor security!");
   }
}
Úgy tűnik, minden rendben van. Van egy elég koherens rendszerünk, amely több modulból áll. Mindegyiküknek megvan a maga viselkedése. Ha új modulokra van szükségünk, akkor ezeket is felvehetjük, mert van egy elég egyszerűen megvalósítható felületünk. De gondoljuk át, hogyan fog működni a monitoring rendszerünk. Névtelen osztályok - 3Alapvetően csak 3 objektumot kell létrehoznunk – GeneralIndicatorMonitoringModule, ErrorMonitoringModule, SecurityModule– és startMonitoring()mindegyiken meghívnunk kell a metódust. Vagyis csak 3 objektumot kell létrehoznunk és 1 metódussal hívnunk meg rajtuk.

public class Main {

   public static void main(String[] args) {

       GeneralIndicatorMonitoringModule generalModule = new GeneralIndicatorMonitoringModule();
       ErrorMonitoringModule errorModule = new ErrorMonitoringModule();
       SecurityModule securityModule = new SecurityModule();

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
Konzol kimenet:

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
És ilyen kevés munkával megírtuk a teljes rendszert: 3 osztály és egy felület! És mindezt 6 kódsor eléréséhez. Másrészt mik a lehetőségeink? Hát nem túl menő, hogy megírtuk ezeket az "egyszeri" órákat. De hogyan tudjuk ezt orvosolni? Itt anonim belső osztályok jönnek a segítségünkre! A mi esetünkben így néznek ki:

public class Main {

   public static void main(String[] args) {

       MonitoringSystem generalModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor general indicators!");
           }
       };

       

MonitoringSystem errorModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor errors!");
           }
       };

       MonitoringSystem securityModule = new MonitoringSystem() {
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor security!");
           }
       };

       generalModule.startMonitoring();
       errorModule.startMonitoring();
       securityModule.startMonitoring();
   }
}
Találjuk ki, mi a helyzet! Úgy tűnik, interfészobjektumot hozunk létre:

MonitoringSystem generalModule = new MonitoringSystem() {
   
@Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
};
De már régóta tudjuk, hogy interfész objektumokat nem tudunk létrehozni! És ez így van – ez lehetetlen. Valójában nem ezt csináljuk. Amikor írunk:

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
a következő történik a Java gépen belül:
  1. Létrejön egy névtelen Java osztály, amely megvalósítja az MonitoringSysteminterfészt.
  2. Amikor a fordító ilyen osztályt lát, megköveteli az interfész összes metódusának megvalósítását MonitoringSystem(ezt 3-szor csináltuk).
  3. Ennek az osztálynak az egyik objektuma létrejön. Ügyeljen a kódra:

MonitoringSystem generalModule = new MonitoringSystem() {
   
};
Pontosvessző van a végén! Okkal van ott. Egyszerre deklaráljuk az osztályt (kapcsos kapcsos zárójelekkel), és létrehozunk belőle egy példányt (a segítségével ();). Mindhárom objektumunk felülírja a startMonitoring()módszert a maga módján. Végül egyszerűen hívjuk ezt a módszert mindegyiknél:

generalModule.startMonitoring();
errorModule.startMonitoring();
securityModule.startMonitoring();
Konzol kimenet:

Starting to monitor general indicators! 
Starting to monitor errors! 
Starting to monitor security!
Ez az! Elértük a célunkat: létrehoztunk három MonitoringSystemobjektumot, három különböző módon felülírtunk egy metódust, és háromszor meghívtuk. Mindhárom modul sikeresen meghívásra került, és fut. Ezzel együtt programunk felépítése is sokkal egyszerűbb lett! Végül is a GeneralIndicatorMonitoringModule, ErrorMonitoringModule, és SecurityModuleosztályok most teljesen eltávolíthatók a programból! Egyszerűen nincs szükségünk rájuk – nagyszerű munkát végeztünk nélkülük. Ha minden névtelen osztályunknak más viselkedésre van szüksége, például saját specifikus metódusaira, amelyekkel a többi nem rendelkezik, könnyen hozzáadhatjuk őket:

MonitoringSystem generalModule = new MonitoringSystem() {
  
   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor general indicators!");
   }
  
   public void someSpecificMethod() {

       System.out.println("Specific method only for the first module");
   }
};
Az Oracle dokumentációja egy jó javaslatot ad : "Használja a [névtelen osztályokat], ha csak egyszer kell helyi osztályt használnia." Az anonim osztály teljes értékű belső osztály. Ennek megfelelően hozzáfér a külső osztály változóihoz, beleértve a statikus és privát változókat is:

public class Main {

   private static int currentErrorCount = 23;

   public static void main(String[] args) {

       MonitoringSystem errorModule = new MonitoringSystem() {
          
           @Override
           public void startMonitoring() {
               System.out.println("Starting to monitor errors!");
           }

           public int getCurrentErrorCount() {

               return currentErrorCount;
           }
       };
   }
}
Van bennük valami közös a helyi osztályokkal: csak azon a metóduson belül láthatóak, amelyben deklarálták őket. A fenti példában az errorModuleobjektum metóduson kívüli elérésére tett kísérletek main()sikertelenek. És van még egy fontos korlátozás, amelyet az anonim osztályok „őseiktől” (belső osztályaiktól) örökölnek: egy névtelen osztály nem tartalmazhat statikus változókat és metódusokat . A fenti példában, ha megpróbáljuk getCurrentErrorCount()statikussá tenni a metódust, a fordító hibát generál:

// Error! Inner classes cannot have static declarations
public static int getCurrentErrorCount() {

   return currentErrorCount;
}
Ugyanezt az eredményt kapjuk, ha statikus változót próbálunk deklarálni:

MonitoringSystem errorModule = new MonitoringSystem() {

   // Error! Inner classes cannot have static declarations!
   static int staticInt = 10;

   @Override
   public void startMonitoring() {
       System.out.println("Starting to monitor errors!");
   }

};
És a mai óránk véget ért! De annak ellenére, hogy megvizsgáltuk a beágyazott osztályok utolsó csoportját, még nem fejeztük be ezt a témát. Mit fogunk még megtudni a beágyazott osztályokról? Minden bizonnyal hamarosan megtudod! :)
Hozzászólások
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION