Det er en smerte å måtte endre parametrene til en funksjon; du må endre alle andre anrop til den funksjonen for å unngå feil. Men du kan komme rundt dette ved å bruke bare én parameter: et konfigurasjonsobjekt.
Her er et dumt eksempel på en funksjon for å lage en robot:
funksjon generereRobot (armer: int, personlighet: String): Robot var robot: Robot = ny Robot (); for (var jeg: int = 0; i < arms; i++) //create arm and add it to robot if (personality == "evil") robot.commands = "Destroy mankind."; else robot.commands = "Bake cookies." return robot; generateRobot(2, "evil");
Nå er det samme eksempel, ved hjelp av et konfigurasjonsobjekt:
funksjon generateRobot (conf: Object): Robot var robot: Robot = ny robot (); for (var jeg: int = 0; i < conf.arms; i++) //create arm and add it to robot if (conf.personality == "evil") robot.commands = "Destroy mankind."; else robot.commands = "Bake cookies." return robot; generateRobot(arms:2, personality:"evil");
Jeg har fremhevet linjene som krever endring; Du kan se at det ikke er mye forskjell.
Så hvis det ikke er noen forskjell, hvorfor ville vi plage å gjøre det på den andre måten? Tross alt gjør det faktisk funksjonen litt vanskeligere å bruke; mens før vår IDE kunne gi oss denne informasjonen om parameterne, forventes funksjonen:
... nå kan det bare gi oss dette:
Anta at du vil legge til et par flere parametre: en som spesifiserer materialet som skal brukes og en annen for å angi hvilken farge laser skal være. Det er ikke for vanskelig, i begge tilfeller:
funksjon generereRobot (armer: int, personlighet: String, materiale: String, laserColor: String): Robot var robot: Robot = ny Robot (); for (var jeg: int = 0; i < arms; i++) //create arm and add it to robot if (personality == "evil") robot.commands = "Destroy mankind."; else robot.commands = "Bake cookies." switch (material) case "wood": //wooden robot break; case "steel": default: //steel robot break; robot.laser = new Laser(); robot.laser.color = laserColor; return robot; generateRobot(2, "evil", "steel", "red");
funksjon generateRobot (conf: Object): Robot var robot: Robot = ny robot (); for (var jeg: int = 0; i < conf.arms; i++) //create arm and add it to robot if (conf.personality == "evil") robot.commands = "Destroy mankind."; else robot.commands = "Bake cookies." switch (conf.material) case "wood": //wooden robot break; case "steel": default: //steel robot break; robot.laser = new Laser(); robot.laser.color = conf.laserColor; return robot; generateRobot(arms:2, personality:"evil", material:"steel", laserColor:"red");
Så langt, fortsatt ikke mye av en forskjell. Hva om du vil at robotene dine til alle har rød lasere som standard? Enkel igjen. Uten et konfigurasjonsobjekt, trenger du bare å endre metodesignaturen (the funksjon
linje), og deretter kan du fjerne det siste argumentet fra funksjonsanropet:
funksjon generereRobot (armer: int, personlighet: String, materiale: String, laserColor: String = "rød"): Robot // dette er det samme generateRobot (2, true, "steel"); // Jeg fjernet det siste argumentet
Med et konfigurasjonsobjekt er det litt vanskeligere - men ikke mye:
funksjon generateRobot (conf: Object): Robot if (! conf.laserColor) conf.laserColor = "red"; var robot: Robot = ny robot (); for (var jeg: int = 0; i < conf.arms; i++) //create arm and add it to robot if (conf.personality == "evil") robot.commands = "Destroy mankind."; else robot.commands = "Bake cookies." switch (conf.material) case "wood": //wooden robot break; case "steel": default: //steel robot break; robot.laser = new Laser(); robot.laser.color = conf.laserColor; return robot; generateRobot(arms:2, personality:"evil", material:"steel"); //I removed the last argument
Greit. Nå antar du at du setter nesten alle robotene dine til å være onde (jeg mener, hvorfor ikke?), Så det er faktisk en slags smerte å skrive "ondskap" som en parameter hver gang. Naturligvis vil du sette "ondskap" som standard - men du ikke vil sette et standard materiale.
Den eneste måten du kan gjøre dette på, med et vanlig sett med funksjonsparametere, er å bytte rekkefølgen til personlighet
og materiale
parametere:
funksjon generereRobot (armer: int, materiale: String, personlighet: String = "ondskap", laserColor: String = "rød"): Robot
Åh, men nå må du bytte rekkefølgen av argumentrunden på hver enkelt funksjonsanrop!
generereRobot (2, "onde", "stål"); // virker ikke lenger
Et konfigurasjonsobjekt gir deg ikke dette problemet. Sjekk det ut:
funksjon generateRobot (conf: Object): Robot if (! conf.laserColor) conf.laserColor = "red"; hvis (! conf.personality) conf.personality = "evil" // dette er det samme generateRobot (arms: 2, material: "steel"); // ingen "personlighet" parameter? ikke noe problem!
Ryddig! Alle dine gamle generateRobot ()
Funksjonsanrop fortsetter å fungere, men du kan opprette nye samtaler som ikke plager å spesifisere personlighet
.
Du kan selv bestemme deg for å bli kvitt personlighet
parameteren totalt:
funksjon generateRobot (conf: Object): Robot if (! conf.laserColor) conf.laserColor = "red"; hvis (! conf.personality) conf.personality = "evil" var robot: Robot = ny robot (); for (var jeg: int = 0; i < conf.arms; i++) //create arm and add it to robot robot.commands = "Destroy mankind."; switch (conf.material) case "wood": //wooden robot break; case "steel": default: //steel robot break; robot.laser = new Laser(); robot.laser.color = conf.laserColor; return robot;
Ovennevnte versjon av funksjonen refererer ikke til conf.personality
i det hele tatt - men du får ikke en feil hvis du fortsatt har anrop slik:
generateRobot (arms: 2, personality: "evil", material: "steel");
Selvfølgelig kan du få noen forvirrede brukere hvis du har anrop slik:
generateRobot (arms: 2, personality: "good", material: "steel");
... siden alle roboter er nå onde. Men i det minste vil koden kompilere.
Av samme grunn kan du endre rekkefølgen på argumentene uten at det er matte i det hele tatt, og til og med legge til nye parametere som ikke gjør noe enda:
generateRobot (material: "steel", laserColor: "green", armer: 2, stemme: "Mr. T");
Koden for å angi standardinnstillingene er lett å forstå så langt, men det vil være veldig irriterende å strekke seg hvis vi trenger mange parametere:
hvis (! conf.laserColor) conf.laserColor = "rød"; hvis (! conf.personality) conf.personality = "evil"
La oss skrive litt mer generell kode for å takle det:
var standard: Objekt = laserColor: rød, personlighet: "ondskap" for (var-nøkkel: String i standardinnstillinger) if (! conf [key]) conf [key] = standard [key];
At til
sløyfen kan være litt forvirrende, så jeg vil bryte den ned. Først, se på dette:
for (var-nøkkel: String i standardinnstillinger) trace (nøkkel);
Dette er en for i
loop, som vil skrive ut navnene på nøklene inni misligholde
gjenstand:
laserColor personlighet
Se etter denne linjen:
spor (standarden [ "laserColor"]);
Dette vil utgjøre rød
- det er det samme som å skrive spore (defaults.laserColor)
.
Etter dette, se på dette eksemplet:
var eksempel: Objekt = demo: "test"; spor (eksempel [ "demo"]); spor (eksempel [ "foo"]);
Hva tror du dette vil produsere?
Vi vil, eksempel [ "demo"]
er det samme som example.demo
, som tilsvarer "test"
. Men example.foo
eksisterer ikke, så eksempel [ "foo"]
vil returnere null
. Dette betyr at !eksempel [ "foo"]
(Merk utropstegnet) vil tilsvare ekte
.
Sett alt sammen, og du bør kunne forstå hvorfor denne koden fungerer:
var standard: Objekt = laserColor: rød, personlighet: "ondskap" for (var-nøkkel: String i standardinnstillinger) if (! conf [key]) conf [key] = standard [key];
Gi meg en rop i kommentarene hvis du trenger en hånd!
For en enda raskere versjon, prøv dette:
funksjon generateRobot (conf: Object = null): Robot var conf: Objekt = conf || ; var standard: Objekt = laserColor: rød, personlighet: "ondskap" for (var nøkkel: String i standardinnstillinger) conf [key] = conf [key] || standarder [k];
Endringen i Linje 1 (og Ny Linje 2) betyr at selv conf
objektet selv er valgfritt, så du kan bare ringe generateRobot ()
. (Selvfølgelig må du endre koden for å håndtere verdiene som for øyeblikket ikke har standardinnstillinger.)
Som nevnt ovenfor kan IDE ikke gi deg noen tips om hvilke parametere en funksjon forventer, hvis den funksjonen bruker et konfigurasjonsobjekt. Dette er en stor ulempe, da det kan gjøre koden din veldig vanskelig å bruke; du må huske hvilke parametere som går inn i conf
objekt, samt alle navn og typer.
Men vi kan fortsatt vise denne informasjonen til koderen når det trengs; vi må bare gjøre det manuelt, slik som:
/ ** * Generer en robot, basert på parametrene gitt. * @param conf Konfigurasjonsobjekt. Forventer: * armer (int) Antall våpenroboter skal ha. * Personlighet (String) Personlighet av robot. Kan være "onde" eller "gode". Standard til "onde". * Material (String) Hva roboten skal utarbeides av. Kan være "stål" eller "tre" på dette tidspunktet. * LaserColor (String) Farge på robotens laser. Standard til "rød". * stemme (String) Vokal styling av robot. For tiden ikke implementert. * @return Den ferdige roboten. * / funksjon generateRobot (conf: Object): Robot //
Nå, hvis jeg begynner å ringe til denne funksjonen i FlashDevelop (min IDE valg), ser jeg dette:
Visst, det er litt vondt å holde dette manuelt oppdatert, men i mange tilfeller er det verdt det.
Jeg hevder ikke at du skal bruke et konfigurasjonsobjekt for hver eneste funksjon du lager fra nå av; bare tenk på det som et annet nyttig verktøy i ditt arsenal.
Personlig finner jeg det et spesielt nyttig mønster når jeg bygger det første utkastet til et sett av klasser som alle trenger å jobbe sammen. Den ekstra fleksibiliteten til a conf
gir meg så mye mer fleksibilitet, frigjør meg til zip rundt alle de forskjellige funksjonene og endrer hvordan de kaller hverandre uten å bekymre seg for å bryte koden ved å sette inn eller fjerne en parameter.
Husk fordelene:
Det er ulempene med å bruke enkle gjenstander som jeg har, skjønt - spesielt hvis du gjør det i et prosjekt som går forbi prototypingstrinnet. Sjekk ut de gode kommentarene nedenfor for mer informasjon!