begrepet adgangskontroll gjør det mulig for oss å begrense hvordan typer, funksjoner og andre deklarasjoner kan nås med annen kode. Swift tilbyr fem ulike nivåer av adgangskontroll, og å gjøre full bruk av dem kan være avgjørende for å skrive programmer som har klart skilt bekymringer og en robust struktur.

når vi definerer en ny type, egenskap eller funksjon I Swift, har den tilgangsnivået internal som standard. Det betyr at det vil være synlig for all annen kode som lever i samme modul — for eksempel en app, en systemutvidelse, et rammeverk eller En Swift-pakke.

la oss for eksempel si at vi bygger en shoppingapp, og at vi har definert en klasse som heterPriceCalculator som lar oss beregne totalprisen for en rekke produkter:

siden vi for øyeblikket ikke angir noe eksplisitt tilgangsnivå, vil vår PriceCalculator klasse (og dens calculatePrice metode) være tilgjengelig fra hvor som helst i appen vår. Men hvis vi ønsker å dele vår nye klasse med andre moduler (vi kan for eksempel implementere den innenfor et rammeverk som vi deler mellom vår hovedapp og en utvidelse, eller En tilhørende Apple Watch-app), må vi gjøre det public for at det skal være synlig i disse eksterne sammenhenger:

men endringen ovenfor er ikke helt nok. Mens vi nå kan finne klassen vår utenfor modulen som den er definert i, kan vi ikke opprette noen forekomster av den-siden den (implisitte) initialisatoren er, akkurat som enhver annen kode, internal som standard. For å fikse det, la oss definere en public initializer, som vi vil forlate tom siden det ikke er noe arbeid som skal gjøres i det:

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

Vi er nå i stand til å finne, initialisere og ringe vår PriceCalculator både innenfor og utenfor modulen-fantastisk. Men la oss nå si at vi også ønsker å underklasse det for å endre det, eller for å legge til ny funksjonalitet i den. Selv om det for øyeblikket er mulig i sin egen modul, er det igjen noe som er forhindret utenfor det.

for å endre det, må Vi bruke Swifts for tiden mest åpne nivå for tilgangskontroll, som er riktig navngitt open:

open class PriceCalculator { ...}

med den ovennevnte endringen på plass kan vi nå lage tilpassede underklasser av PriceCalculator hvor som helst-som kan ha nye initialisatorer, nye egenskaper og nye metoder. Slik kan vi bruke det til å implementere en DiscountedPriceCalculator, som lar oss bruke en gitt discount til alle prisberegninger:

Ovenfor definerer Vi en helt ny prisberegningsmetode, men det vil uten tvil være mye mer hensiktsmessig å overstyre og endre den eksisterende calculatePrice – metoden som vi arvet fra vår grunnklasse i stedet. På den måten ville det ikke være noen forvirring rundt hvilken metode å ringe, og vi kunne holde våre to klasser konsistente.

for å kunne gjøre det, må vi igjen markere den opprinnelige erklæringen-denne gangen vår calculatePrice metodedeklarasjon-som open:

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

med ovenstående på plass kan vi nå fritt overstyre calculatePrice, i stedet for å måtte lage en egen metode:

Så det er internal, public og open – som brukes til å gradvis åpne en erklæring for offentlig bruk og endring. Men vi kan selvfølgelig også gå den andre veien, og skjule deler av koden vår fra å bli oppdaget og brukt. I begynnelsen kan det virke tvilsomt hva verdien er i å gjøre det, men det kan virkelig hjelpe OSS med Å gjøre VÅR API mye smalere og fokusert — noe som igjen kan gjøre det lettere å forstå, teste og bruke.

så la oss nå gå helt til den andre siden av tilgangsnivåspekteret, og ta en titt på det mest restriktive nivået — private. Enhver type, egenskap eller metode som er merket som private, vil bare være synlig innenfor sin egen type(som også inkluderer utvidelser for den typen som er definert i samme fil).

Alt som bør betraktes som en privat implementeringsdetalj av en gitt type, bør uten tvil merkes som private. For eksempel var vår priskalkulatorens discount eiendom fra før egentlig bare ment å bli brukt i sin egen klasse – så la oss gå videre og gjøre den eiendommen privat:

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

vår tidligere implementering vil fortsette å fungere nøyaktig på samme måte som før, siden discount vil forbli helt synlig i vår DiscountedPriceCalculator klasse. Men hvis vi ønsket å utvide synligheten litt for å også inkludere andre typer definert i samme fil, må vi bruke fileprivate — som gjør akkurat det det høres ut som, det holder en erklæring privat i filen som den er definert i:

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

med den ovennevnte endringen på plass, kan vi nå få tilgang til vår discount eiendom fra relatert kode definert i samme fil — for eksempel denne utvidelsen på UIAlertController som lar oss enkelt vise en prisbeskrivelse for en rekke produkter i et varsel:

når det gjelder gratis funksjoner, typer og utvidelser, private og fileprivate virker nøyaktig det samme. De er bare forskjellige når de brukes på deklarasjoner som er definert i en type.

så, for å oppsummere, er Disse fem nivåene av tilgangskontroll Som Swift for tiden tilbyr:

  • private holder en egenskap eller funksjon privat innenfor den omsluttende typen, inkludert eventuelle utvidelser av den typen som er definert i samme fil. Når den brukes på en toppnivåtype, funksjon eller utvidelse, fungerer den på samme måte som fileprivate.
  • fileprivate gjør en erklæring synlig i hele filen som den er definert i, mens den gjemmer den fra all annen kode.
  • internal er standard tilgangsnivå, og gjør en erklæring synlig i hele modulen som den er definert i.
  • public viser en funksjon, type, utvidelse eller egenskap utenfor modulen.
  • open gjør det mulig for en klasse å være underklasse, og en funksjon eller egenskap som skal overstyres, utenfor modulen.

generelt er det ofte best å starte med det mest restriktive tilgangsnivået som en gitt erklæring praktisk talt kan ha, og deretter åpne ting senere om nødvendig. På den måten begrenser vi mulighetene for samspill mellom våre ulike typer og funksjoner, som i begynnelsen kan virke som en dårlig ting, men er ofte virkelig viktig for å bygge vedlikeholdbare og velstrukturerte systemer.

Takk for at du leser! 🚀

(Merk at denne artikkelen ikke gikk inn i mutasjonsspesifikke tilgangsmodifikatorer, for eksempel private(set). De vil bli dekket av En Annen Grunnleggende artikkel i fremtiden.)

Støtte Swift Av Sundell ved å sjekke ut denne sponsoren:

Instabug: Løs feil, krasjer og andre problemer mye raskere ved hjelp av detaljerte stakkspor, nettverkslogger og UI-hendelser som Instabug automatisk legger til hver feilrapport. Brukes både av meg og tusenvis av iOS utviklingsteam rundt om i verden. Prøv det gratis og integrere det med bare en enkelt linje med kode.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.