Lær Java for Android Development Inner Classes

I denne opplæringen blir du kjent med begrepet indre klasser i Java-de klassene hvis omfang og definisjon er omtalt i en annen klasse. Du vil også lære om anonyme indre klasser, som brukes ganske ofte når de utvikles med Android SDK.

Android-applikasjoner er skrevet i Java, et objektorientert programmeringsspråk. I denne opplæringen lærer du om indre klasser, når og hvorfor du skal bruke dem og hvordan de fungerer. Du lærer også å lage nye objekter dynamisk ved hjelp av anonyme indre klasser.

Hva du trenger

Teknisk trenger du ikke noe verktøy for å fullføre denne opplæringen, men du vil sikkert trenge dem til å utvikle Android-applikasjoner.

For å utvikle Android-applikasjoner (eller Java-programmer, for øvrig), trenger du et utviklingsmiljø for å skrive og bygge programmer. Eclipse er et svært populært utviklingsmiljø (IDE) for Java og den foretrukne IDE for Android-utvikling. Det er fritt tilgjengelig for Windows, Mac og Linux operativsystemer.

For fullstendige instruksjoner om hvordan du installerer Eclipse (inkludert hvilke versjoner som støttes) og Android SDK, se Android-utviklerens nettsted.

Hva er en indre klasse?

De fleste klassene i Java er klasser på toppnivå. Disse klassene, og objektene de definerer, er frittstående. Du kan også lage nestede klasser for å tydelig inkapslere og definere underordnede objekter som bare betyr noe i sammenheng med ytre klassen. Nestede klasser kalles indre klasser.

Inner klasser kan ha alle funksjonene i en vanlig klasse, men deres omfang er begrenset. Inner klasser har en annen fordel: De har full tilgang til klassen de er nest i. Denne funksjonen gjør indre klasser perfekt til å implementere adapterfunksjonalitet som iteratorer.

Her er et eksempel på en toppklasse klasse med to indre klasser:

 offentlig klasse Bruker // Brukerfelt, inkludert variabler av typen LoginInfo og UserPreferences // Diverse brukermetoder klasse LoginInfo // Innloggingsfelt // Logg inn / Logg ut metoder // Kan få tilgang til brukerfelt / metoder klasse Innstillinger // Bruker preferansefelt // Få / Sett inn preferansemetoder // Tilbakestill preferansemetode // Kan få tilgang til brukerfelt / metoder 

I dette eksemplet har brukerklassen to indre klasser: LoginInfo og Preferences. Mens alle brukerrelaterte data og funksjonalitet kunne defineres i brukerklassen, kan de enklere å lese og vedlikeholde koden ved hjelp av de indre klassene for å formell funksjonalitet. De indre klassene LoginInfo og Preferences har også tilgang til de beskyttede / private feltene og metodene som er tilgjengelige i brukerklassen, som de ikke ellers kunne ha på grunn av sikkerhet, dersom de ble definert som frittstående klasser seg selv.

Det er viktig å huske at de indre klassene egentlig bare eksisterer for å hjelpe utvikleren til å organisere kode; kompilatoren behandler indre klasser akkurat som enhver annen klasse, bortsett fra at de indre klassene har et begrenset omfang, og er derfor knyttet til klassen de er definert med. På en annen måte ville du ikke kunne bruke eller instantiere klassene LoginInfo eller Preferences, med unntak av en forekomst av brukerklassen, men de indre klassene kunne få tilgang til alle felt eller metoder som er tilgjengelige i den ytre klassen Bruker, etter behov.

Bruke statiske nestede klasser

En spesiell bruk for nestede klasser er statisk nestede klasser. En statisk indre klasse definerer oppførsel som ikke er knyttet til en bestemt objekteksempel, men gjelder i alle tilfeller. For eksempel kan vi legge til en tredje nestet klasse, denne gangen statisk, til brukerklassen for å kontrollere serverrelatert funksjonalitet:

 offentlig klasse Bruker // Brukerfelt, inkludert variabler av typen LoginInfo og UserPreferences // Diverse brukermetoder klasse LoginInfo  offentlig statisk klasse ServerInfo  // Serverinformasjon gjelder alle forekomster av Bruker 

Fordi det er offentlig, kan denne statiske nestede klassen bli instantiated ved hjelp av følgende nye setning:

 User.ServerInfo sInfo = ny User.ServerInfo (); 

Ytre klassen trenger ikke å være instantiated for å utføre denne instantiation, og dermed bruk av klassenavnet. Som sådan har en statisk nestet klasse, i motsetning til en ikke-statisk innlejret klasse (aka indre klasse), ikke tilgang til medlemmer av ytre klasse - de kan ikke engang bli instansiert.

Kraften til Anonym Inner Klasser

Android bruker anonyme indre klasser til stor effekt. Anonyme indre klasser er i utgangspunktet utviklerkortografi, slik at utvikleren kan lage, definere og bruke et tilpasset objekt i en "linje". Du har kanskje sett eksempler på bruk av anonym indre klasse i prøvekode og ikke engang innså det.
For å opprette en anonym indre klasse, gir du bare den høyre siden av definisjonen. Begynn med det nye søkeordet, etterfulgt av klassen eller grensesnittet du ønsker å utvide eller implementere, etterfulgt av klasses definisjonen. Dette vil opprette klassen og returnere den som en verdi som du kan bruke til å ringe en metode.
Når vi bruker en anonym indre klasse, blir ikke det oppnådde objektet tildelt et navn (dermed begrepet anonyme). Bivirkningen, selvfølgelig, er at objektet blir brukt bare en gang. For eksempel er det vanlig å bruke en anonym indre klasse for å konstruere en egendefinert versjon av et objekt som en returverdi. For eksempel, her utvider vi klassen Truck (forutsatt at den er definert andre steder og har et felt som heter mpg og to metoder, start () og stopp ():

 Lastbil getTruck () returner ny lastebil () int mpg = 3; void start () / * start implementering * / void stop () / * stopp implementering * /;  

La oss nå se på praktiske eksempler på anonyme indre klasser som brukes i Android.

Bruke en anonym indre klasse for å definere en lytter

Android-utviklere bruker ofte anonyme indre klasser til å definere spesialiserte lyttere, som registrerer tilbakeringinger for spesifikk oppførsel når en hendelse oppstår. For eksempel, for å lytte etter klikk i en View-kontroll, må utvikleren kalle metoden setOnClickListener (), som tar en enkelt parameter: et View.OnClickListener-objekt.
Utviklere bruker rutinemessig den anonyme indre klasseteknikken til å lage, definere og bruke deres tilpassede View.OnClickListener, som følger:

 Button aButton = (Button) findViewById (R.id.MyButton); aButton.setOnClickListener (ny View.OnClickListener () public void onClick (Vis v) // Bruker klikket min knapp, gjør noe her!); 

Bruke en anonym indre klasse for å starte en tråd

La oss se på et annet eksempel. Det er ganske vanlig å definere en ny trådklasse, gi implementeringen av sin run () -metode, og start den tråden, alt på en gang:

 ny tråd () public void run () doWorkHere ();  .start(); 

Bruke en navngitt indre klasse

Bruk av anonyme indre klasser for lyttere i Android er så vanlig at det er praktisk talt andre natur å gjøre det. Hvorfor vil du da ikke bruke dem? La oss svare på dette gjennom et hypotetisk eksempel.
La oss si at du har en skjerm som har 100 knapper på den (vi sa hypotetiske, ikke sant?). La oss nå si at hver knapp, når den trykkes, gjør det nøyaktig samme ting. I dette tilfellet vil vi bare lytte etter klikk og skøyte teksten fra visningsobjektet som ble sendt inn (teksten som vises på knappen som ble klikket):
Her er pseudokoden for å gjøre det:

 Knapp [] knapper = getAllOneHundredButtonsAsArray (); for (knappeknapp: knapper) button.setOnClickListener (ny View.OnClickListener () offentlig ugyldig påClick (Vis v) showToast (v.getText ()););  

Kort og elegant, så hva er galt med det? Ved hver iterasjon blir et nytt OnClickListener-objekt instantiated. Siden hver er nøyaktig det samme, er det ingen grunn til å skape 100 av dem. I stedet kan du opprette en enkelt, navngitt, indre klasse, instantiere den en gang, og deretter sende den til setOnClickListener () -metoden. For eksempel:

 klasse MyActivity utvider Aktivitet public void myMethod () MyClickHandler handler = ny MyClickHandler (); Knapp [] knapper = getAllOneHundredButtonsAsArray (); for (knappeknapp: knapper) button.setOnClickListener (handler);  klasse MyClickHandler implementerer View.OnClickListener public void onClick (Vis v) showToast (((Button) v) .getText ());  

Hvis du foretrekker anonymitet, kan du fortsatt tilordne en anonym indre klasse til en variabel og bruke det slik som:

 klasse MyActivity utvider Aktivitet public void myMethod () View.OnClickListener handler = ny View.OnClickListener () public void onClick (Vis v) showToast (((Button) v) .getText ()); ; Knapp [] knapper = getAllOneHundredButtonsAsArray (); for (knappeknapp: knapper) button.setOnClickListener (handler);  

Metoden er opp til deg, men husk at potensielle minne- og ytelsesproblemer som kan forårsake en masse objekter, kan ha.

En kommentar på nyanser

Denne opplæringen er ment å være en innledende guide til indre klasser i Java. Det er stiloverveielser og nyanser når du bruker indre klasser på ulike og kreative måter. Utover det kan du utforske videre for å lære mer om interne effekter og marginale ytelsesforskjeller som kan dukke opp når du bruker nestede klasser på forskjellige måter. Alt dette er imidlertid langt utenfor omfanget av denne opplæringen.

En rask notat på terminologi

Selv om vi har forsøkt å være konsistente med terminologien på nestede og indre klasser, er terminologien ikke alltid konsekvent fra ulike online og offline ressurser. Følgende er en liste over vilkår fra den nåværende Sun / Oracle dokumentasjonen, som er like god som noen for å være autoritative på Java:

  • Nested Class: en klasse definert i en annen klasse
  • Statisk Nested Class: en statisk klasse definert i en annen klasse
  • Inner klasse: en ikke-statisk innlejret klasse definert i en annen klasse
  • Lokal Inner klasse: en klasse definert i en metode
  • Anonym Inner Class: en navngitt klasse definert i en metode

Forvirret? Du kan bruke java.lang.Class-metodene kalt isLocalClass () og isAnonymous () klasse på instantiated klasser for å bestemme et par av disse egenskapene. En Oracle bloggoppføring forsøker også å klargjøre situasjonen litt, med et fint Venn-diagram.

Wrapping Up

Java-programmeringsspråket støtter nestede klasser, slik at utvikleren har stor fleksibilitet når det gjelder å definere objekter. Inner klasser kan brukes til å organisere klassens funksjonalitet eller å definere spesialiserte atferd som ellers ville kreve at utvikleren utsettes for klassedata og funksjonalitet som egentlig ikke burde bli utsatt. Statiske indre klasser kan brukes til å definere felt og funksjonalitet som gjelder i alle tilfeller av en klasse. Endelig anonyme indre klasser gir en nyttig stenografi for utviklere som ønsker å lage, definere og bruke et tilpasset objekt på en gang.