Hittil har vi dekket grunnleggende om Swift programmeringsspråket. Hvis du fulgte med, bør du nå ha en solid forståelse av variabler, konstanter, funksjoner og nedleggelser. Det er nå på tide å bruke det vi har lært og bruke den kunnskapen til Swifts objektorienterte strukturer.
For å forstå konseptene som er omtalt i denne opplæringen, er det viktig at du har en grunnleggende forståelse av objektorientert programmering. Hvis du ikke er kjent med klasser, objekter og metoder, anbefaler jeg deg først å lese om disse emnene før du fortsetter med denne opplæringen.
eBok: Objektorientert programmering med Swift
I denne leksjonen skal vi utforske de grunnleggende byggeblokkene i objektorientert programmering i Swift, klasser og strukturer. I Swift, klasser og strukturer føler og oppfører seg veldig like, men det er en rekke sentrale forskjeller som du trenger å forstå for å unngå vanlige fallgruver.
I Mål-C er klasser og strukturer svært forskjellige. Dette er ikke sant for Swift. I Swift kan for eksempel både klasser og strukturer ha egenskaper og metoder. I motsetning til C-strukturer kan strukturer i Swift utvides, og de kan også overholde protokollene.
Det åpenbare spørsmålet er: "Hva er forskjellen mellom klasser og strukturer?" Vi vil besøke dette spørsmålet senere i denne opplæringen. La oss først undersøke hva en klasse ser ut i Swift.
Før vi begynner å jobbe med klasser og strukturer, vil jeg gjerne avklare noen vanlige bruksbetingelser i objektorientert programmering. Vilkårene klasser, objekter, og forekomster Forvirre ofte folk som er ny til objektorientert programmering. Derfor er det viktig at du vet hvordan Swift bruker disse vilkårene.
EN klasse er en blåkopi eller mal for en forekomst av den klassen. Begrepet "objekt" brukes ofte til å referere til en forekomst av en klasse. I Swift er klasser og strukturer imidlertid svært like, og det er derfor lettere og mindre forvirrende å bruke begrepet "forekomst" for både klasser og strukturer.
Tidligere i denne serien jobbet vi med funksjoner. I sammenheng med klasser og strukturer refererer vi vanligvis til funksjoner som metoder. Metoder er med andre ord funksjoner som tilhører en bestemt klasse eller struktur. I sammenheng med klasser og strukturer kan du bruke begge termer om hverandre, siden hver metode er en funksjon.
La oss få føttene våte og definere en klasse. Brann opp Xcode og opprett en ny lekeplass. Fjern innholdet på lekeplassen og legg til følgende klasses Definisjon.
klasse person
De klasse
Søkeordet indikerer at vi definerer en klasse som heter Person. Gjennomføringen av klassen er pakket inn i et par krøllete braces. Selv om Person
klassen er ikke veldig nyttig i sin nåværende form, det er en skikkelig, funksjonell Swift klasse.
Som i de fleste andre objektorienterte programmeringsspråk kan en klasse ha egenskaper og metoder. I det oppdaterte eksemplet nedenfor definerer vi tre egenskaper:
fornavn
, en variabel egenskap av typen string?
etternavn
, en variabel egenskap av typen string?
fødested
: en konstant egenskap av type string
klasse Person var firstName: String? var lastnavn: streng? la birthPlace = "Belgium"
Som eksemplet illustrerer, er definisjon av egenskaper i en klassdefinisjon likt å definere vanlige variabler og konstanter. Vi bruker Var
søkeord for å definere en variabel egenskap og la
søkeord for å definere en fast eiendom.
Ovenstående egenskaper er også kjent som lagrede egenskaper. Senere i denne serien lærer vi om beregnede egenskaper. Som navnet antyder, er lagrede egenskaper egenskaper som er lagret av klasseeksemplet. De ligner egenskaper i Objective-C.
Det er viktig å merke seg at hver lagret eiendom må ha en verdi etter initialisering eller defineres som en valgfri type. I eksemplet ovenfor gir vi fødested
eiendom en innledende verdi på "Belgia"
. Dette forteller Swift at fødestedet er av typen string
. Senere i denne artikkelen tar vi en nærmere titt på initialiseringen og undersøker hvordan det knytter seg til initialisering av egenskaper.
Selv om vi definerte fødested
eiendom som en konstant, er det mulig å endre verdien under initialiseringen av a Person
forekomst. Når forekomsten er initialisert, vil fødested
Eiendom kan ikke lenger endres siden vi definerte eiendommen som en fast eiendom med la
søkeord.
Vi kan legge til oppførsel eller funksjonalitet i en klasse gjennom funksjoner eller metoder. I mange programmeringsspråk, metode brukes i stedet for funksjon i sammenheng med klasser og forekomster. Definere en metode er nesten identisk med å definere en funksjon. I det neste eksemplet definerer vi fullt navn()
metode i Person
klasse.
klasse Person var firstName: String? var lastnavn: streng? la birthPlace = "Belgium" func fullName () -> String var deler: [String] = [] hvis la firstName = self.firstName parts + = [firstName] hvis la lastName = self.lastName parts + = [ lastName] returnere parts.joined (separator: "")
Metoden fullt navn()
er nestet i klassen definisjonen. Den aksepterer ingen parametere og returnerer a string
. Gjennomføringen av fullt navn()
metoden er enkel. Gjennom valgfri binding, som vi diskuterte tidligere i denne serien, får vi tilgang til verdiene som er lagret i fornavn
og etternavn
eiendommer.
Vi lagrer for- og etternavnet til Person
forekomme i en matrise og delta i delene med et mellomrom. Årsaken til denne litt vanskelige implementeringen bør være åpenbar: for- og etternavnet kan være tomt, derfor er begge egenskapene av typen string?
.
Vi har definert en klasse med noen få egenskaper og en metode. Hvordan lager vi en forekomst av Person
klasse? Hvis du er kjent med Objective-C, vil du elske konsistensen til følgende utdrag.
la john = Person ()
Instantiating en forekomst av en klasse er veldig lik å påkalle en funksjon. For å opprette en forekomst blir klassens navn etterfulgt av et par parenteser, og returverdien er tilordnet en konstant eller variabel.
I vårt eksempel, konstanten john
peker nå på en forekomst av Person
klasse. Betyr dette at vi ikke kan endre noen av dens egenskaper? Neste eksempel svarer på dette spørsmålet.
john.firstName = "John" john.lastName = "Doe" john.birthPlace = "France"
Vi kan få tilgang til egenskapene til en forekomst ved hjelp av punktsyntaxen. I eksemplet setter vi fornavn
til "John"
, etternavn
til "Doe"
, og fødested
til "Frankrike"
. Før vi trekker noen konklusjoner basert på eksemplet ovenfor, må vi sjekke om eventuelle feil på lekeplassen.
Innstilling fornavn
og etternavn
ser ikke ut som noen problemer. Men tildele "Frankrike"
til fødested
Egenskapen resulterer i en feil. Forklaringen er enkel.
Selv om john
er erklært som en konstant, som ikke hindrer oss fra å modifisere Person
forekomst. Det er imidlertid en advarsel, men bare variable egenskaper kan endres etter initialisering av en forekomst. Egenskaper som er definert som konstant, kan ikke endres når en verdi er tildelt.
En konstant egenskap kan endres under initialisering av en forekomst. Mens fødested
Eiendommen kan ikke endres en gang a Person
Eksempel er opprettet, klassen ville ikke være veldig nyttig hvis vi bare kunne instantiere Person
forekomster med en fødested for "Belgia". La oss lage Person
klassen litt mer fleksibel.
Initialisering er en fase i levetiden til en forekomst av en klasse eller struktur. Under initialisering forbereder vi forekomsten for bruk ved å fylle sine egenskaper med innledende verdier. Initialiseringen av en forekomst kan tilpasses ved å implementere en initialiserer, en spesiell type metode. La oss definere en initialiserer for Person
klasse.
klasse Person var firstName: String? var lastnavn: streng? la birthPlace = "Belgium" init () birthPlace = "France" ...
Vi har definert en initialiserer, men vi løper inn i flere problemer. Ta en titt på feilen kompilatoren kaster på oss.
Ikke bare er initialisatoren meningsløs, kompilatoren advarer også oss om at vi ikke kan endre verdien av fødested
eiendom siden den allerede har en innledende verdi. Vi kan løse feilen ved å fjerne initialverdien til fødested
eiendom.
klasse Person var firstName: String? var lastnavn: streng? la birthPlace: String init () birthPlace = "France" ...
Merk at navnet på initialisatoren, i det()
, er ikke på forhånd av func
søkeord. I motsetning til initiativer i Objective-C returnerer en initialiserer i Swift ikke forekomsten som initialiseres.
En annen viktig detalj er hvordan vi setter inn fødested
eiendom med en innledende verdi. Vi satte fødested
eiendom ved å bruke eiendommens navn, men det er også fint å være mer eksplisitt som dette.
init () self.birthPlace = "France"
De selv-
søkeord refererer til forekomsten som blir initialisert. Dette betyr at self.birthPlace
refererer til fødested
eiendom av forekomsten. Vi kan utelate selv-
, som i det første eksemplet, fordi det ikke er forvirring om hvilken eiendom vi refererer til. Dette er ikke alltid tilfelle, skjønt. La meg forklare hva jeg mener.
Initialiseringen vi definerte er ikke veldig nyttig for øyeblikket, og det løser ikke problemet vi startet med: å kunne definere fødselsstedet til en person under initialisering.
I mange situasjoner vil du sende initialverdier til initialisatoren for å tilpasse forekomsten du instanser. Dette er mulig ved å opprette en tilpasset initialiserer som aksepterer en eller flere argumenter. I det følgende eksempelet oppretter vi en tilpasset initialiserer som aksepterer ett argument, fødested
, av type string
.
init (birthPlace: String) self.birthPlace = birthPlace
To ting er verdt å peke på. Først må vi få tilgang til fødested
eiendom gjennom self.birthPlace
for å unngå tvetydighet siden det lokale parameternavnet er lik fødested
. For det andre, selv om vi ikke har angitt et eksternt parameternavn, oppretter Swift som standard et eksternt parameternavn som er lik det lokale parameternavnet.
I det følgende eksemplet ordner vi en annen Person
eksempel ved å påkalle den tilpassede initialiseringen vi nettopp har definert.
la maxime = Person (birthPlace: "France") print (maxime.birthPlace)
Ved å overføre en verdi for fødested
parameter til initialisatoren, kan vi tilordne en tilpasset verdi til konstanten fødested
eiendom under initialisering.
Som i mål-C kan en klasse eller struktur ha flere initiativer. I det følgende eksempel oppretter vi to Person
forekomster. I første linje bruker vi standardinitialiseringen. I den andre linjen bruker vi den tilpassede initialiseringen vi definerte tidligere.
la p1 = Person () la p2 = Person (fødested: "Frankrike")
Strukturer er overraskende lik klasser, men det er noen viktige forskjeller. La oss begynne med å definere en grunnleggende struktur.
struct lommebok var dollar: Int var cents: Int
Ved første øyekast er den eneste forskjellen bruken av struct
søkeord i stedet for klasse
søkeord. Eksemplet viser også oss en alternativ tilnærming til å levere innledende verdier til egenskaper. I stedet for å sette en innledende verdi for hver eiendom, kan vi gi egenskaper en startverdi i initialiseringen av strukturen. Swift vil ikke kaste en feil, fordi den også inspiserer initialisatoren for å bestemme den opprinnelige verdien og typen av hver eiendom.
Du kan begynne å lure på hva forskjellen er mellom klasser og strukturer. Ved første øyekast ser de ut identiske i form og funksjon, med unntak av klasse
og struct
søkeord. Det er imidlertid en rekke viktige forskjeller.
Klasser støtter arv, mens strukturer ikke gjør det. Følgende eksempel illustrerer dette. Arvsmønsteret er uunnværlig i objektorientert programmering, og i Swift er det en viktig forskjell mellom klasser og strukturer.
klasse Person var firstName: String? var lastnavn: streng? la birthPlace: String init (birthPlace: String) self.birthPlace = birthPlace klasse Student: Person var skole: String? la student = Student (birthPlace: "France")
I eksempelet ovenfor er det Person
klassen er forelder eller superklasse av Student
klasse. Dette betyr at Student
Klassen arver egenskapene og oppførselen til Person
klasse. Den siste linjen illustrerer dette. Vi initialiserer en Student
eksempel ved å påkalle den tilpassede initialisereren definert i Person
klasse.
Følgende konsept er trolig det viktigste konseptet i Swift du lærer i dag, forskjellen mellom verdi typer og referansetyper. Strukturer er verdi typer, noe som betyr at de er bestått etter verdi. Et eksempel illustrerer dette konseptet best.
struktur Punkt var x: Int var y: Int init (x: Int, y: Int) self.x = x self.y = y var punkt1 = Punkt (x: 0, y: 0) var punkt2 = punkt1 punkt1.x = 10 utskrift (punkt1.x) // 10 utskrift (punkt2.x) // 0
Vi definerer en struktur, Punkt
, å inkapslere dataene for å lagre en koordinat i et todimensjonalt rom. Vi instanser point1
med x
lik 0
og y
lik 0
. Vi tildeler point1
til poeng2
og sett x
koordinat av point1
til 10
. Hvis vi sender ut x
koordinere begge punkter, oppdager vi at de ikke er like.
Strukturer er bestått av verdi, mens klasser er bestått ved referanse. Hvis du planlegger å fortsette å jobbe med Swift, må du forstå forrige setning. Når vi tildelte point1
til poeng2
, Swift opprettet en kopi av point1
og tilordnet den til poeng2
. Med andre ord, point1
og poeng2
hvert punkt til en annen forekomst av Punkt
struktur.
La oss nå gjenta denne øvelsen med Person
klasse. I det følgende eksemplet ordner vi en Person
Installer, sett dens egenskaper, tilordne menneske1
til person2
, og oppdatere fornavn
tilhører menneske1
. For å se hva som går med referansemidler for klasser, utfører vi verdien av fornavn
eiendom av begge deler Person
forekomster.
var person1 = Person (birthPlace: "Belgium") person1.firstName = "Jane" person1.lastName = "Gjør" var person2 = person1 person1.firstName = "Janine" print (person1.firstName!) // Janine print (person2. fornavn!) // Janine
Eksemplet viser at klasser er referansetyper. Dette betyr at menneske1
og person2
referer til eller referer til det samme Person
forekomst. Ved tildeling menneske1
til person2
, Swift lager ikke en kopi av menneske1
. De person2
variabel punkter til det samme Person
forekomst menneske1
peker på. Endre fornavn
tilhører menneske1
påvirker også fornavn
tilhører person2
, fordi de refererer til det samme Person
forekomst.
Som jeg nevnte flere ganger i denne artikkelen, er klasser og strukturer veldig like. Hva skiller klasser og strukturer er svært viktig. Hvis de ovennevnte begrepene ikke er klare, oppfordrer jeg deg til å lese artikkelen en gang til for å la de konseptene vi dekket synke inn.
I denne delen av Swift From Scratch har vi begynt å utforske grunnleggende om objektorientert programmering i Swift. Klasser og strukturer er de grunnleggende byggeblokkene i de fleste Swift-prosjekter, og vi lærer mer om dem i de neste leksjonene i denne serien.
I neste leksjon fortsetter vi utforskningen av klasser og strukturer ved å se nærmere på eiendommer og arv.
Hvis du vil lære hvordan du bruker Swift 3 til å kode sanntidsprogrammer, sjekk ut kurset ditt Opprett IOS Apps With Swift 3. Enten du er ny i iOS app-utvikling eller ønsker å skifte bryteren fra Objective-C, dette kurset vil komme i gang med Swift for app utvikling.