Programmering

Indre klasser

Spørsmål: Så hva er indre klasser bra for uansett?

EN: Indre klasser hekker i andre klasser. En normal klasse er et direkte medlem av en pakke, en toppklasse. Indre klasser, som ble tilgjengelig med Java 1.1, kommer i fire smaker:

  • Statiske medlemsklasser
  • Medlemsklasser
  • Lokale klasser
  • Anonyme klasser

La oss ta en rask titt på hver i sin tur.

Kort fortalt a statisk medlemsklasse er et statisk medlem av en klasse. Som en hvilken som helst annen statisk metode, har en statisk medlemsklasse tilgang til alle statiske metoder for den overordnede eller øverste klassen.

Som en statisk medlemsklasse, a medlemsklasse er også definert som medlem av en klasse. I motsetning til den statiske varianten er medlemsklassen eksempelspesifikk og har tilgang til alle metoder og medlemmer, til og med foreldrenes dette henvisning.

Lokalt klasser blir deklarert i en blokk med kode og er bare synlige i den blokken, akkurat som alle andre metodevariabler.

Til slutt, en anonym klasse er en lokal klasse som ikke har noe navn.

For å svare på det spesifikke spørsmålet ditt, vil jeg fokusere på medlemmene og anonyme indre klasser, siden det er de du sannsynligvis vil møte og bruke. For meg kan fordelene med indre klasser deles inn i tre kategorier: en objektorientert fordel, en organisatorisk fordel og en tilbakekallingsfordel.

Den objektorienterte fordelen

Etter min ydmyke mening er det viktigste trekket i den indre klassen at den lar deg gjøre ting til gjenstander som du normalt ikke ville forvandlet til gjenstander. Det gjør at koden din blir enda mer objektorientert enn den ville vært uten indre klasser.

La oss se på medlemsklassen. Siden forekomsten er medlem av sin overordnede forekomst, har den tilgang til hvert medlem og metode i foreldrene. Ved første øyekast virker det kanskje ikke så mye; vi har allerede den slags tilgang fra en metode i foreldreklassen. Imidlertid tillater medlemsklassen oss å ta logikken ut av foreldren og objektivisere den. For eksempel kan en treklasse ha en metode og mange hjelpermetoder som utfører et søk eller gange på treet. Fra et objektorientert synspunkt er treet et tre, ikke en søkealgoritme. Du trenger imidlertid intim kunnskap om treets datastrukturer for å utføre et søk.

En indre klasse tillater oss å fjerne logikken og plassere den i sin egen klasse. Så fra et objektorientert synspunkt har vi tatt funksjonalitet ut der den ikke hører hjemme og har satt den i sin egen klasse. Gjennom bruk av en indre klasse har vi frakoblet søkealgoritmen fra treet. Nå, for å endre søkealgoritmen, kan vi bare bytte i en ny klasse. Jeg kunne fortsette, men det åpner koden vår for mange av fordelene som tilbys med objektorienterte teknikker.

Den organisatoriske fordelen

Objektorientert design er ikke alles ting, men heldigvis gir indre klasser mer. Fra et organisatorisk synspunkt tillater indre klasser oss å videre organisere pakkestrukturen vår gjennom bruk av navnerom. I stedet for å dumpe alt i en flat pakke, kan klassene nestes ytterligere i klassene. Uten uttrykk, uten indre klasser, var vi begrenset til følgende hierarkistruktur:

pakke1 klasse 1 klasse 2 ... klasse n ... pakke n 

Med indre klasser kan vi gjøre følgende:

pakke 1 klasse 1 klasse 2 klasse 1 klasse 2 ... klasse n 

Brukt forsiktig kan indre klasser gi et strukturelt hierarki som mer naturlig passer til klassene dine.

Tilbakekallingsfordelen

Indre medlemsklasser og anonyme klasser gir begge en praktisk metode for å definere tilbakeringing. Det mest åpenbare eksemplet er relatert til GUI-kode. Anvendelsen av tilbakeringingen kan imidlertid utvide seg til mange domener.

De fleste Java GUI-er har en slags komponent som starter en actionPerformed () metodeanrop. Dessverre har de fleste utviklere rett og slett sitt hovedvinduimplement ActionListener. Som et resultat deler alle komponentene det samme actionPerformed () metode. For å finne ut hvilken komponent som utførte handlingen, er det normalt en gigantisk, stygg bryter i actionPerformed () metode.

Her er et eksempel på en monolitisk implementering:

offentlig klasse SomeGUI utvider JFrame implementerer ActionListener {beskyttet JButton-knapp1; beskyttet JButton-knapp2; ... beskyttet JButton-knappN; offentlig ugyldig handling Utført (ActionEvent e) {if (e.getSource () == button1) {// gjør noe} annet hvis (e.getSource () == button2) {... du får bildet 

Når du ser brytere eller store hvis/hvis ikke blokker, høye alarmklokker skal begynne å ringe i tankene dine. Generelt er slike konstruksjoner dårlig objektorientert design siden en endring i en del av koden kan kreve en tilsvarende endring i bryteruttalelsen. Indre medlemsklasser og anonyme klasser tillater oss å komme vekk fra byttet actionPerformed () metode.

I stedet kan vi definere en indre klasse som implementeres ActionListener for hver komponent som vi ønsker å lytte til. Det kan føre til mange indre klasser. Imidlertid kan vi unngå store bryteruttalelser og ha den ekstra bonusen å kapsle inn handlingslogikken vår. Videre kan denne tilnærmingen forbedre ytelsen. I en bryter der det er n sammenligninger, kan vi forvente n / 2 sammenligninger i gjennomsnittstilfelle. Indre klasser tillater oss å sette opp en 1: 1-korrespondanse mellom handlingsutøveren og handlingslytteren. I en stor brukergrensesnitt kan slike optimaliseringer ha betydelig innvirkning på ytelsen. En anonym tilnærming kan se slik ut:

offentlig klasse SomeGUI utvider JFrame {... knappemedlemerklæringer ... beskyttet ugyldig buildGUI () {button1 = ny JButton (); button2 = ny JButton (); ... button1.addActionListener (new java.awt.event.ActionListener () {public void actionPerformed (java.awt.event.ActionEvent e) {// do something}}); .. gjenta for hver knapp 

Ved å bruke indre medlemsklasser vil det samme programmet se slik ut:

offentlig klasse SomeGUI utvider JFrame {... knappedeklarasjoner // indre klassedefinisjoner klasse Button1Håndterer implementerer ActionListener {offentlig ugyldig handlingPerformert (ActionEvent e) {// gjør noe}} ... definer en indre medlemsklasse for hver knappbeskyttet ugyldig buildGUI () {// initialisere knappene button1 = ny JButton (); button2 = ny JButton (); ... // registrer en indre klassehandling lytterforekomst // for hver knapp-knapp1.addActionListener (ny Button1Handler ()); .. gjenta for hver knapp 

Siden indre klasser har tilgang til alt i foreldrene, kan vi flytte enhver logikk som ville ha dukket opp i en monolitisk actionPerformed () implementering til en indre klasse.

Jeg foretrekker å bruke medlemsklasser som tilbakeringing. Det er imidlertid et spørsmål om personlig preferanse. Jeg føler bare at for mange anonyme klasser roter koden. Jeg føler også at anonyme klasser kan bli uhåndterlige hvis de er større enn en eller to linjer.

Ulemper?

Som med alt annet, må du ta det gode med det dårlige. Indre klasser har sine ulemper. Fra et vedlikeholdssynspunkt kan uerfarne Java-utviklere finne den indre klassen vanskelig å forstå. Bruk av indre klasser vil også øke det totale antallet klasser i koden din. Dessuten, fra et utviklingssynspunkt, kommer de fleste Java-verktøy litt kort på deres støtte til indre klasser. For eksempel bruker jeg IBMs VisualAge for Java for min daglige koding. Mens indre klasser kompileres i VisualAge, er det ingen nettleser eller mal for indre klasser. I stedet må du bare skrive den indre klassen direkte inn i klassedefinisjonen. Det gjør dessverre surfing i indre klasse vanskelig. Det er også vanskelig å skrive siden du mister mange av VisualAges kodefullføringshjelpemidler når du skriver inn klassedefinisjonen eller bruker en indre klasse.

Tony Sintes er seniorkonsulent i ObjectWave, med spesialisering i telekommunikasjon. Sintes, en Sun-sertifisert Java 1.1-programmerer og Java 2-utvikler, har jobbet med Java siden 1997.

Lær mer om dette emnet

  • "Inner Classes Specification" fra Sun, gir en grundig titt på indre klasser

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

Denne historien, "Indre klasser" ble opprinnelig utgitt av JavaWorld.

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