Programmering

Design med statiske medlemmer

Selv om Java i stor grad er objektorientert, er det ikke en ren objektorientert språk. En av grunnene til at Java ikke er rent objektorientert, er at ikke alt i det er et objekt. For eksempel lar Java deg deklarere variabler av primitive typer (int, flyte, boolskosv.) som ikke er gjenstander. Og Java har statiske felt og metoder, som er uavhengige og adskilt fra objekter. Denne artikkelen gir råd om hvordan du bruker statiske felt og metoder i et Java-program, samtidig som du beholder et objektorientert fokus i designene dine.

Levetiden til en klasse i en Java virtual machine (JVM) har mange likheter med levetiden til et objekt. Akkurat som et objekt kan ha tilstand, representert av verdiene til dets forekomstvariabler, kan en klasse ha tilstand, representert av verdiene til klassevariablene. Akkurat som JVM setter forekomstvariabler til standardinnledende verdier før de kjører initialiseringskoder, setter JVM klassevariabler til standardinnledende verdier før de kjører initialiseringskoder. Og i likhet med gjenstander kan klasser samles i søppel hvis det ikke lenger refereres til det i applikasjonen som kjører.

Likevel eksisterer det betydelige forskjeller mellom klasser og objekter. Den viktigste forskjellen er kanskje måten instans og klassemetoder påberopes: instansemetoder er (for det meste) dynamisk bundet, men klassemetoder er statisk bundet. (I tre spesielle tilfeller er ikke forekomstmetoder dynamisk bundet: påkalling av private forekomstmetoder, påkalling av i det metoder (konstruktører), og påkallelser med super nøkkelord. Se Ressurser for mer informasjon.)

En annen forskjell mellom klasser og objekter er graden av skjuling av data gitt av de private tilgangsnivåene. Hvis en forekomstvariabel erklæres privat, er det bare forekomstmetoder som har tilgang til den. Dette gjør at du kan sikre integritetsdataene for forekomsten og gjøre objekter trådsikre. Resten av programmet har ikke direkte tilgang til disse forekomstvariablene, men må gå gjennom forekomstmetodene for å manipulere forekomstvariablene. I et forsøk på å få en klasse til å oppføre seg som et godt designet objekt, kan du gjøre klassevariabler private og definere klassemetoder som manipulerer dem. Likevel får du ikke så god garanti for trådsikkerhet eller til og med dataintegritet på denne måten, fordi en bestemt type kode har et spesielt privilegium som gir dem direkte tilgang til private klassevariabler: forekomstmetoder og til og med initialiseringer av eksempel variabler, kan få tilgang til de private klassevariablene direkte.

Så de statiske feltene og metodene til klasser, selv om de på mange måter ligner på forekomstfeltene og metodene til objekter, har betydelige forskjeller som bør påvirke måten du bruker dem i design.

Behandler klasser som gjenstander

Når du designer Java-programmer, vil du sannsynligvis støte på mange situasjoner der du føler behov for et objekt som fungerer på noen måter som en klasse. Du kan for eksempel ønske deg et objekt hvis levetid samsvarer med en klasse. Eller du vil kanskje ha et objekt som, i likhet med en klasse, begrenser seg til en enkelt forekomst i et gitt navn mellomrom.

I designsituasjoner som disse kan det være fristende å lage en klasse og bruke den som et objekt for å definere klassevariabler, gjøre dem private og definere noen offentlige klassemetoder som manipulerer klassevariablene. Som et objekt har en slik klasse tilstand. Som et godt designet objekt er variablene som definerer staten private, og omverdenen kan bare påvirke denne tilstanden ved å påkalle klassemetodene.

Dessverre eksisterer det noen problemer med denne "class-as-object" -tilnærmingen. Fordi klassemetoder er statisk bundet, vil ikke klasse-som-objektet ditt nyte fleksibilitetsfordelene ved polymorfisme og oppkast. (For definisjoner av polymorfisme og dynamisk binding, se artikkelen Design Techniques, Composition versus Arv.) Polymorfisme er mulig, og oppkasting er nyttig ved dynamisk binding, men klassemetoder er ikke dynamisk bundet. Hvis noen underklasser klassen din som objekt, vil de ikke kunne overstyring klassemetodene dine ved å erklære klassemetoder med samme navn; de vil bare kunne gjemme seg dem. Når en av disse omdefinerte klassemetodene påkalles, vil JVM velge metodeimplementering for å utføre ikke av klassen til et objekt ved kjøretid, men etter typen variabel på kompileringstidspunktet.

I tillegg er trådsikkerheten og dataintegriteten som du oppnår ved den grundige implementeringen av klassemetodene i klassen som objekt, som et hus bygget av halm. Trådsikkerheten og dataintegriteten din blir garantert så lenge alle bruker klassemetodene til å manipulere tilstanden som er lagret i klassevariablene. Men en uforsiktig eller clueless programmerer kan, med tillegg av en forekomstmetode som får tilgang til dine private klassevariabler direkte, utilsiktet puste og puste og blåse trådsikkerheten og dataintegriteten din bort.

Av denne grunn er min hovedretningslinje angående klassevariabler og klassemetoder:

Ikke behandle klasser som gjenstander.

Med andre ord, ikke design med statiske felt og metoder i en klasse som om de var forekomstfeltene og metodene til et objekt.

Hvis du vil ha tilstand og atferd hvis levetid samsvarer med en klasse, må du unngå å bruke klassevariabler og klassemetoder for å simulere et objekt. I stedet lager du et faktisk objekt og bruk en klassevariabel for å holde en referanse til det og klassemetoder for å gi tilgang til objektreferansen. Hvis du vil sikre at bare en forekomst av en eller annen tilstand og oppførsel eksisterer i et enkelt navnerom, må du ikke prøve å designe en klasse som simulerer et objekt. Opprett i stedet en singleton - et objekt garantert bare har én forekomst per navneplass.

Så hva er klassemedlemmer bra for?

Etter min mening er det beste tankesettet å dyrke når du designer Java-programmer å tenke objekter, objekter, objekter. Fokuser på å designe flotte objekter, og tenk på klasser primært som tegninger for objekter - strukturen der du definerer forekomstvariablene og forekomstmetodene som utgjør de veldesignede objektene dine. I tillegg til det, kan du tenke på klasser som å tilby noen spesielle tjenester som objekter ikke kan tilby, eller ikke kan tilby så elegant. Tenk på klasser som:

  • riktig sted å definere "verktøymetoder" (metoder som tar input og gir utdata bare gjennom passerte parametere og returverdien)
  • en måte å kontrollere tilgangen til objekter og data på

Nyttighetsmetoder

Metoder som ikke manipulerer eller bruker tilstanden til et objekt eller klasse, kaller jeg "verktøymetoder". Verktøysmetoder returnerer bare en eller annen verdi (eller verdier) beregnet utelukkende fra data som sendes til metoden som parametere. Du bør gjøre slike metoder statiske og plassere dem i klassen som er tettest knyttet til tjenesten metoden gir.

Et eksempel på en verktøymetode er String copyValueOf (char [] data) metode for klassen String. Denne metoden produserer sin produksjon, en returverdi av typen String, utelukkende fra inngangsparameteren, en rekke røyes. Fordi copyValueOf () verken bruker eller påvirker tilstanden til noe objekt eller klasse, det er en verktøymetode. Og som alle verktøy må være, copyValueOf () er en klassemetode.

Så en av de viktigste måtene å bruke klassemetoder er som verktøymetoder - metoder som returnerer output beregnet utelukkende fra inputparametere. Annen bruk av klassemetoder involverer klassevariabler.

Klassevariabler for skjuling av data

En av de grunnleggende forskriftene i objektorientert programmering er dataskjuling - å begrense tilgangen til data for å minimere avhengigheten mellom delene av et program. Hvis et bestemt stykke data har begrenset tilgjengelighet, kan disse dataene endres uten å bryte de delene av programmet som ikke får tilgang til dataene.

Hvis det for eksempel bare er behov for et objekt av forekomster av en bestemt klasse, kan en referanse til det lagres i en privat klassevariabel. Dette gir alle forekomster av denne klassen praktisk tilgang til det objektet - forekomsten bruker det bare direkte - men ingen andre koder noe annet sted i programmet kan komme til det. På en lignende måte kan du bruke pakketilgang og beskyttede klassevariabler for å redusere synligheten til objekter som må deles av alle medlemmer av en pakke og underklasser.

Offentlige klassevariabler er en annen historie. Hvis en offentlig klassevariabel ikke er endelig, er den en global variabel: den ekle konstruksjonen som er motsatsen til datahemmingen. Det er aldri noen unnskyldning for en offentlig klassevariabel, med mindre den er endelig.

Endelige offentlige klassevariabler, enten primitive type eller objektreferanse, tjener et nyttig formål. Variabler av primitive typer eller av type String er ganske enkelt konstanter, som generelt bidrar til å gjøre programmer mer fleksible (lettere å endre). Kode som bruker konstanter er lettere å endre fordi du kan endre den konstante verdien på ett sted. Offentlige endelige klassevariabler av referansetyper lar deg gi global tilgang til objekter som trengs globalt. For eksempel, System.in, System.out, og System.err er offentlige endelige klassevariabler som gir global tilgang til standard inngangsoutput og feilstrømmer.

Dermed er den viktigste måten å se klassevariabler på som en mekanisme for å begrense tilgjengeligheten til (mening, å skjule) variabler eller objekter. Når du kombinerer klassemetoder med klassevariabler, kan du implementere enda mer kompliserte tilgangsretningslinjer.

Bruke klassemetoder med klassevariabler

Bortsett fra å fungere som verktøymetoder, kan klassemetoder brukes til å kontrollere tilgang til objekter lagret i klassevariabler - spesielt for å kontrollere hvordan objektene blir opprettet eller administrert. To eksempler på denne typen klassemetode er setSecurityManager () og getSecurityManager () metoder for klassen System. Sikkerhetsbehandling for et program er et objekt som, i likhet med standard inngangs-, utdata- og feilstrømmer, er nødvendig mange forskjellige steder. I motsetning til standard I / O-strømobjekter lagres en referanse til sikkerhetsbehandling ikke i en offentlig endelig klassevariabel. Security manager-objektet lagres i en privat klassevariabel, og sett- og get-metodene implementerer en spesiell tilgangspolicy for objektet.

Javas sikkerhetsmodell setter en spesiell begrensning på sikkerhetslederen. Før Java 2 (tidligere kjent som JDK 1.2) begynte et program livet uten sikkerhetsansvarlig (getSecurityManager () returnert null). Den første samtalen til setSecurityManager () etablerte sikkerhetssjefen, som deretter ikke fikk lov til å endre. Eventuelle påfølgende samtaler til setSecurityManager () ville gi et sikkerhets unntak. I Java 2 starter applikasjonen alltid med en sikkerhetsbehandling, men lik de forrige versjonene setSecurityManager () metoden vil tillate deg å endring sikkerhetssjefen en gang, på det meste.

Sikkerhetslederen gir et godt eksempel på hvordan klassemetoder kan brukes i forbindelse med private klassevariabler for å implementere en spesiell tilgangspolicy for objekter som det refereres til av klassevariablene. Bortsett fra verktøymetoder, tenk på klassemetoder som middel til å etablere spesielle tilgangspolitikker for objektreferanser og data lagret i klassevariabler.

Retningslinjer

Hovedpoenget med råd gitt i denne artikkelen er:

Ikke behandle klasser som gjenstander.

Hvis du trenger et objekt, må du lage et objekt. Begrens bruken av klassevariabler og metoder for å definere verktøymetoder og implementere spesielle typer tilgangspolitikker for objekter og primitive typer som er lagret i klassevariabler. Selv om det ikke er et rent objektorientert språk, er Java likevel objektorientert i stor grad, og designene dine skal gjenspeile det. Tenk objekter.

Neste måned

Neste måned Designteknikker artikkelen vil være den siste i denne kolonnen. Jeg begynner snart å skrive en bok basert på Design Techniques-materialet, Fleksibel Java, og vil plassere det materialet på nettstedet mitt mens jeg går. Så følg prosjektet sammen og send meg tilbakemelding. Etter en pause på en måned eller to, er jeg tilbake kl JavaWorld og SunWorld med en ny spalte fokusert på Jini.

En forespørsel om lesermedvirkning

Jeg oppfordrer dine kommentarer, kritikk, forslag, flammer - alle slags tilbakemeldinger - om materialet som presenteres i denne kolonnen. Hvis du er uenig i noe, eller har noe å legge til, vennligst gi meg beskjed.

Du kan delta i et diskusjonsforum viet til dette materialet, legge inn en kommentar via skjemaet nederst i artikkelen, eller sende meg en e-post direkte ved hjelp av lenken i biografen min nedenfor.

Bill Venners har skrevet programvare profesjonelt i 12 år. Basert i Silicon Valley, tilbyr han programvarekonsulent- og opplæringstjenester under navnet Artima Software Company. Gjennom årene har han utviklet programvare for forbrukerelektronikk, utdanning, halvleder og livsforsikringsindustri. Han har programmert på mange språk på mange plattformer: monteringsspråk på forskjellige mikroprosessorer, C på Unix, C ++ på Windows, Java på nettet. Han er forfatter av boken Inside the Java Virtual Machine, utgitt av McGraw-Hill.
$config[zx-auto] not found$config[zx-overlay] not found