begrebet adgangskontrol gør det muligt for os at begrænse, hvordan typer, funktioner og andre erklæringer kan tilgås med anden kode. Hurtig tilbyder fem forskellige niveauer af adgangskontrol, og at udnytte dem fuldt ud kan være afgørende for at skrive programmer, der har klart adskilte bekymringer og en robust struktur.

når vi definerer en ny type, egenskab eller funktion i Hurtig, har den som standard adgangsniveauet internal. Det betyder, at det vil være synligt for al anden kode, der lever inden for det samme modul — såsom en app, en systemudvidelse, en ramme eller en hurtig pakke.

Lad os som et eksempel sige, at vi bygger en shopping-app, og at vi har defineret en klasse kaldet PriceCalculator, der lader os beregne den samlede pris for en række produkter:

da vi i øjeblikket ikke angiver noget eksplicit adgangsniveau, vil vores PriceCalculator klasse (og dens calculatePrice metode) være tilgængelig hvor som helst i vores app. Men hvis vi ønsker at dele vores nye klasse med andre moduler (vi kan for eksempel implementere det inden for en ramme, som vi deler mellem vores hovedapp og en udvidelse eller en ledsagende Apple-ur-app), så bliver vi nødt til at gøre det public for at det skal være synligt inden for disse eksterne sammenhænge:

ovenstående ændring er dog ikke helt nok. Mens vi nu kan finde vores klasse uden for det modul, Det er defineret I, kan vi ikke oprette nogen forekomster af det — da dets (implicitte) initialisator er, ligesom enhver anden kode, internal som standard. For at løse det, lad os definere en public initialisator, som vi vil forlade tom, da der ikke er noget egentligt arbejde, der skal gøres inden for det:

public class PriceCalculator { public init() {} ...}

vi er nu i stand til at finde, initialisere og ringe til vores PriceCalculator både inden for og uden for dets modul — fantastisk. Men lad os nu sige, at vi også ønsker at underklasse det for at ændre det eller tilføje ny funktionalitet til det. Selvom det i øjeblikket er muligt inden for sit eget modul, er det igen noget, der forhindres uden for det.

for at ændre det, skal vi bruge det mest åbne niveau af adgangskontrol, som er passende navngivet open:

open class PriceCalculator { ...}

med ovenstående ændring på plads kan vi nu oprette brugerdefinerede underklasser på PriceCalculator hvor som helst — som kan have nye initialisatorer, nye egenskaber og nye metoder. Sådan kan vi bruge det til at implementere en DiscountedPriceCalculator, som lader os anvende en given discount på alle prisberegninger:

ovenfor definerer vi en helt ny prisberegningsmetode, men det ville nok være meget mere hensigtsmæssigt at tilsidesætte og ændre den eksisterende calculatePrice metode, som vi arvede fra vores basisklasse i stedet. På den måde ville der ikke være nogen forvirring omkring hvilken metode man skulle kalde, og vi kunne holde vores to klasser konsistente.

for at kunne gøre det, skal vi igen markere den oprindelige erklæring-denne gang vores calculatePrice metodedeklaration-som open:

open class PriceCalculator { public init() {} open func calculatePrice(for products: ) -> Int { ... }}

med ovenstående på plads kan vi nu frit tilsidesætte calculatePrice i stedet for at skulle oprette en separat metode:

så det er internal, public og open — som bruges til gradvist at åbne en erklæring til offentlig brug og modifikation. Men vi kan selvfølgelig også gå den anden vej og skjule dele af vores kode fra at blive opdaget og brugt. I starten kan det virke tvivlsomt, hvad værdien er ved at gøre det, men det kan virkelig hjælpe os med at gøre vores API meget mere smal og fokuseret — hvilket igen kan gøre det lettere at forstå, teste og bruge.

så lad os nu gå helt til den anden side af adgangsniveauspektret og se på det mest restriktive niveau — private. Enhver type, egenskab eller metode, der er markeret som private, vil kun være synlig inden for sin egen type (som også inkluderer udvidelser på den type, der er defineret i den samme fil).

alt, hvad der skal betragtes som en privat implementeringsdetalje af en given type, skal uden tvivl markeres som private. For eksempel var vores prisberegner discount ejendom fra før virkelig kun beregnet til at blive brugt inden for sin egen klasse — så lad os gå videre og gøre denne ejendom privat:

class DiscountedPriceCalculator: PriceCalculator { private let discount: Int ...}

vores tidligere implementering vil fortsætte med at fungere nøjagtigt på samme måde som før, da discount forbliver helt synlig inden for vores DiscountedPriceCalculator klasse. Men hvis vi ønskede at udvide synligheden lidt til også at omfatte andre typer defineret i samme fil, skal vi bruge fileprivate – hvilket gør præcis, hvad det lyder som, det holder en erklæring privat i filen, som den er defineret i:

class DiscountedPriceCalculator: PriceCalculator { fileprivate let discount: Int ...}

med ovenstående ændring på plads kan vi nu få adgang til vores discount ejendom fra relateret kode defineret i den samme fil — såsom Denne udvidelse på UIAlertController som lader os let vise en prisbeskrivelse for en række produkter inden for en advarsel:

når det kommer til gratis funktioner, typer og udvidelser, private og fileprivate handle nøjagtigt det samme. De er kun forskellige, når de anvendes på erklæringer, der er defineret inden for en type.

så for at opsummere er dette de fem niveauer af adgangskontrol, som hurtig i øjeblikket tilbyder:

  • private holder en egenskab eller funktion privat inden for dens omsluttende type, herunder eventuelle udvidelser på den type, der er defineret i den samme fil. Når den anvendes på en type, funktion eller udvidelse på øverste niveau, fungerer den på samme måde som fileprivate.
  • fileprivate gør en erklæring synlig i hele filen, som den er defineret i, mens den skjuler den fra al anden kode.
  • internal er standardadgangsniveauet og gør en erklæring synlig i hele modulet, som det er defineret i.
  • public afslører en funktion, type, udvidelse eller egenskab uden for modulet.
  • open gør det muligt at underklassificere en klasse og tilsidesætte en funktion eller egenskab uden for dens modul.

generelt er det ofte bedst at starte med det mest restriktive adgangsniveau, som en given erklæring praktisk talt kan have, og derefter åbne tingene senere, hvis det er nødvendigt. På den måde begrænser vi mulighederne for interaktion mellem vores forskellige typer og funktioner, som i første omgang kan virke som en dårlig ting, men er ofte virkelig afgørende for at opbygge vedligeholdelige og velstrukturerede systemer.

tak for læsning!

(bemærk, at denne artikel ikke gik ind i mutationsspecifikke adgangsmodifikatorer, såsom private(set). Disse vil blive dækket af en anden grundlæggende artikel i fremtiden.)

Støtte Hurtig af Sundell ved at tjekke denne sponsor:

Instabug: Løs fejl, nedbrud og andre problemer meget hurtigere ved hjælp af de detaljerede stakspor, netværkslogfiler og UI-begivenheder, som Instabug automatisk vedhæfter til hver fejlrapport. Brugt både af mig og tusindvis af iOS-udviklingshold rundt om i verden. Prøv det gratis og integrere det med blot en enkelt linje kode.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.