Programovanie

Vnútorné triedy

Otázka: Na čo sú teda vlastne vnútorné triedy dobré?

A: Vnútorné triedy hniezdia v iných triedach. Normálna trieda je priamym členom balíka, trieda najvyššej úrovne. Vnútorné triedy, ktoré sú dostupné v prostredí Java 1.1, majú štyri príchute:

  • Triedy statických členov
  • Členské triedy
  • Miestne triedy
  • Anonymné triedy

Poďme sa rýchlo pozrieť na každú z nich.

Stručne, a statická trieda členov je statickým členom triedy. Ako každá iná statická metóda, aj trieda statického člena má prístup ku všetkým statickým metódam nadradenej triedy alebo triedy najvyššej úrovne.

Rovnako ako statická členská trieda, a členská trieda je tiež definovaný ako člen triedy. Na rozdiel od statickej odrody je členská trieda špecifická pre jednotlivé inštancie a má prístup k všetkým metódam a členom, dokonca aj k rodičom toto odkaz.

Miestne triedy sú deklarované v rámci bloku kódu a sú viditeľné iba v tomto bloku, rovnako ako akákoľvek iná premenná metódy.

Nakoniec an anonymný trieda je miestna trieda, ktorá nemá meno.

Aby som odpovedal na vašu konkrétnu otázku, zameriam sa na členské a anonymné vnútorné triedy, pretože to sú tie, s ktorými sa pravdepodobne stretnete a ktoré budete používať. Pre mňa sa dajú výhody vnútorných tried rozdeliť do troch kategórií: objektovo-orientovaná výhoda, organizačná výhoda a výhoda spätného volania.

Objektovo orientovaná výhoda

Podľa môjho skromného názoru je najdôležitejšou vlastnosťou vnútornej triedy to, že vám umožňuje meniť veci na objekty, ktoré by ste za normálnych okolností nezmenili na objekty. To umožňuje, aby bol váš kód ešte viac objektovo zameraný, ako by to bolo bez vnútorných tried.

Pozrime sa na triedu členov. Pretože jeho inštancia je členom nadradenej inštancie, má prístup ku každému členovi a metóde v nadradenej inštancii. Na prvý pohľad sa to nemusí zdať veľa; tento druh prístupu už máme v rámci metódy v rodičovskej triede. Členská trieda nám však umožňuje vziať logiku z rodiča a objektivizovať ju. Napríklad trieda stromu môže mať metódu a mnoho pomocných metód, ktoré vyhľadávajú alebo prechádzajú stromom. Z objektového hľadiska je strom strom, nie vyhľadávací algoritmus. Na dokončenie vyhľadávania však potrebujete dôkladné znalosti o dátových štruktúrach stromu.

Vnútorná trieda nám umožňuje odstrániť túto logiku a umiestniť ju do vlastnej triedy. Takže z objektového hľadiska sme odstránili funkčnosť z miesta, kam nepatrí, a zaradili sme ju do svojej vlastnej triedy. Použitím vnútornej triedy sme úspešne oddelili vyhľadávací algoritmus od stromu. Teraz, aby sme zmenili vyhľadávací algoritmus, môžeme jednoducho vymeniť novú triedu. Mohol by som pokračovať, ale to otvára náš kód mnohým výhodám, ktoré poskytujú objektovo orientované techniky.

Organizačná výhoda

Objektovo orientovaný dizajn nie je vecou každého, ale našťastie vnútorné triedy poskytujú viac. Z organizačného hľadiska nám vnútorné triedy umožňujú ďalej organizovať našu štruktúru balíkov pomocou menných priestorov. Namiesto toho, aby ste všetko ukladali do plochého balíka, môžu byť triedy ďalej vnorené do tried. Bez vnútorných tried sme sa výslovne obmedzili na nasledujúcu štruktúru hierarchie:

balík1 trieda 1 trieda 2 ... trieda n ... balík č 

S vnútornými triedami môžeme robiť nasledovné:

balík 1 trieda 1 trieda 2 trieda 1 trieda 2 ... trieda n 

Pri opatrnom používaní môžu vnútorné triedy poskytnúť štruktúrnu hierarchiu, ktorá sa prirodzenejšie hodí k vašim triedam.

Výhoda spätného volania

Triedy vnútorných členov aj anonymné triedy poskytujú pohodlnú metódu na definovanie spätných volaní. Najzrejmejší príklad sa týka kódu GUI. Aplikácia spätného volania sa však môže rozšíriť na mnoho domén.

Väčšina Java GUI má nejaký druh komponentu, ktorý iniciuje actionPerformed () volanie metódy. Väčšina vývojárov má, bohužiaľ, implementáciu svojho hlavného okna ActionListener. Vďaka tomu majú všetky komponenty rovnaké vlastnosti actionPerformed () metóda. Ak chcete zistiť, ktorá zložka vykonala akciu, je v nej obvykle obrovský škaredý prepínač actionPerformed () metóda.

Tu je príklad monolitickej implementácie:

verejná trieda SomeGUI rozširuje JFrame implementuje ActionListener {chránené JButton button1; chránené tlačidlo JButton2; ... chránené tlačidlo JButtonN; public void actionPerformed (ActionEvent e) {if (e.getSource () == button1) {// urobiť niečo} iné if (e.getSource () == button2) {... získate obrázok 

Kedykoľvek uvidíte prepínače alebo veľké ak/ako inak bloky, vo vašej mysli by vám mali začať zvoniť hlasné poplašné zvony. Všeobecne sú tieto konštrukty zlým objektovo orientovaným dizajnom, pretože zmena v jednej časti kódu môže vyžadovať zodpovedajúcu zmenu v príkaze switch. Triedy vnútorných členov a anonymné triedy nám umožňujú dostať sa preč od prechodu actionPerformed () metóda.

Namiesto toho môžeme definovať vnútornú triedu, ktorá sa implementuje ActionListener pre každú zložku, ktorú chceme počúvať. To môže viesť k mnohým vnútorným triedam. Môžeme sa však vyhnúť veľkým príkazom na prepnutie a mať navyše bonus zapuzdrenia našej logiky akcií. Tento prístup navyše môže zlepšiť výkon. V prepínači, kde sú n môžeme očakávať n / 2 porovnania v priemernom prípade. Vnútorné triedy nám umožňujú nastaviť korešpondenciu 1: 1 medzi umelcom a poslucháčom akcií. Vo veľkom grafickom rozhraní môže mať takáto optimalizácia podstatný vplyv na výkon. Anonymný prístup môže vyzerať takto:

verejná trieda SomeGUI rozširuje JFrame {... deklarácie členov tlačidiel ... chránené void buildGUI () {button1 = new JButton (); button2 = new JButton (); ... button1.addActionListener (new java.awt.event.ActionListener () {public void actionPerformed (java.awt.event.ActionEvent e) {// niečo urobiť}}); .. opakujte pre každé tlačidlo 

Použitím tried vnútorných členov by ten istý program vyzeral takto:

public class SomeGUI extends JFrame {... button member declarations // internal class definitions class Button1Handler implements ActionListener {public void actionPerformed (ActionEvent e) {// do something}} ... definujte vnútornú triedu člena pre každé tlačidlo chránené void buildGUI () {// inicializovať tlačidlá button1 = new JButton (); button2 = new JButton (); ... // zaregistruje inštanciu poslucháča akcie vnútornej triedy // pre každé tlačidlo button1.addActionListener (nové Button1Handler ()); .. opakujte pre každé tlačidlo 

Pretože vnútorné triedy majú prístup ku všetkému v rodičovi, môžeme presunúť každú logiku, ktorá by sa objavila v monolite actionPerformed () implementácia do vnútornej triedy.

Ako spätné volania radšej používam členské triedy. To je však otázka osobných preferencií. Mám pocit, že príliš veľa anonymných tried zahlcuje kód. Mám tiež pocit, že anonymné triedy sa môžu stať nepraktickými, ak sú väčšie ako jeden alebo dva riadky.

Nevýhody?

Rovnako ako v prípade všetkého iného, ​​aj v tomto musíte brať dobré a zlé stránky. Vnútorné triedy majú svoje nevýhody. Z hľadiska údržby môže byť pre neskúsených vývojárov v prostredí Java ťažké pochopiť vnútornú triedu. Použitie vnútorných tried tiež zvýši celkový počet tried v kóde. Z vývojového hľadiska navyše väčšina nástrojov Java prichádza s nedostatkom podpory vnútorných tried. Ja napríklad na svoje každodenné kódovanie používam program IBM VisualAge for Java. Aj keď sa vnútorné triedy budú kompilovať v rámci VisualAge, neexistuje prehliadač ani šablóna vnútornej triedy. Namiesto toho musíte jednoducho napísať vnútornú triedu priamo do definície triedy. To nanešťastie sťažuje prechádzanie vnútornou triedou. Je tiež ťažké písať, pretože pri zadávaní do definície triedy alebo použití vnútornej triedy stratíte veľa pomôcok na dokončenie kódu VisualAge.

Tony Sintes je senior konzultant v spoločnosti ObjectWave so špecializáciou na telekomunikácie. Sintes, programátor Java 1.1, ktorý je certifikovaný spoločnosťou Sun, a vývojár Java 2, pracuje s Java od roku 1997.

Získajte viac informácií o tejto téme

  • „Špecifikácia vnútorných tried“ od spoločnosti Sun poskytuje podrobný pohľad na vnútorné triedy

    //java.sun.com/products/jdk/1.1/docs/guide/innerclasses/spec/innerclasses.doc.html

Tento príbeh, „Vnútorné triedy“, bol pôvodne publikovaný spoločnosťou JavaWorld.

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