Komme i gang med mål-C

Introduksjon

Med det grunnleggende om C som er fortsatt friskt i minnet, er det på tide å bli kjent med Objective-C. Hovedforskjellen med C er at Objective-C er et objektorientert programmeringsspråk, mens C er et prosesseringsprogrammeringsspråk. Dette betyr at vi først må forstå objekter og hvordan de relaterer seg til klasser. Andre viktige begreper som vi vil utforske i denne artikkelen er objektmeldinger, innkapsling og arv.


Origins of Objective-C

Mål-C og Kakao er to sentrale komponenter i IOS-plattformen. Til tross for at iOS-plattformen fortsatt er relativt ung, ble Objective-C opprettet tidlig på 1980-tallet på StepStone av Brad Cox og Tom Love. Språket ble opprettet i et forsøk på å kombinere det robuste og smidige C-programmeringsspråket med det elegante Smalltalk-språket. Objektiv-C er en streng supersett av C og, i motsetning til C, er det et høyt programmeringsspråk. Hovedforskjellen mellom C og Objective-C er at sistnevnte er et objektorientert programmeringsspråk, mens C er et prosesseringsprogrammeringsspråk.

Hvordan endte iOS med et språk som ble utviklet på 1980-tallet? Kort etter at NeXT ble grunnlagt av Steve Jobs, lisensierte den Objective-C fra StepStone. NeXT opprettet NeXTSTEP, et verktøy for brukergrensesnitt for NeXT-operativsystemet utviklet i Objective-C. Selv om NeXTSTEP ga et revolusjonerende sett med verktøy, oppnådde NeXT operativsystemet bare lite trekkraft i markedet. I 1996 kjøpte Apple NeXT og NeXTSTEP ble kakao. Sistnevnte gikk vanlig med introduksjonen av OS X i mars 2001 og senere med utgivelsen av iPhone og iOS operativsystemet.


Objektorientert programmering

I prosessprogrammering består et program av en serie prosedyrer eller rutiner som utføres for å nå en bestemt stat. I objektorientert programmering, imidlertid, en samling gjenstander samhandler og samarbeider for å fullføre en oppgave. Selv om sluttresultatet kan være identisk, er metodikken og underliggende paradigmer vesentlig forskjellige. Modularitet og kodegenbruk er to av de viktigste fordelene ved objektorienterte programmeringsspråk som vi snart vil se.


Mål-C, Kakao og Kakao

Utviklere som er nye til iOS og OS X-økosystemene, blir ofte forvirret av forholdet mellom Objective-C, Cocoa (OS X) og Cocoa Touch (iOS). Hva er Cocoa Touch, og hvordan er det relatert til Objective-C? Kakao er Apples opprinnelige applikasjonsprogrammeringsgrensesnitt (API) for iOS- og OS X-plattformene. Mål-C er språket som driver kakao. Mens denne artikkelen primært fokuserer på Objective-C programmeringsspråket, vil vi se nærmere på Cocoa og Cocoa Touch API senere i denne serien.


Klasser, objekter og forekomster

En annen hindring for utviklere som er nye til objektorientert programmering, er forskjellen mellom klasser, objekter og forekomster. En klasse er et kast eller en blåkopi for å skape objekter, mens forekomster er unike hendelser i en klasse. Et objekt er en datastruktur som har en tilstand og oppførsel. Til tross for den subtile forskjellen mellom objekter og forekomster, brukes begge termer ofte utveksling.

La oss ta en titt på et eksempel: brødristere. Før en brødrister er produsert, lager ingeniører en blåkopi, som tilsvarer en klasse. Hver brødrister opprettet fra tegningen er en forekomst eller en unik forekomst av klassen. Selv om hver brødrister er laget av samme tegning (klasse), har de hver sin egen stat (farge, antall spor osv.) Og atferd.

Instansvariabler og innkapsling

Tilstanden til en forekomst er lagret i og definert av dens instansvariabler, eller objektets attributter hvis du vil. Dette bringer oss til et annet sentralt mønster av objektorientert programmering: innkapsling. Innkapsling betyr at den indre representasjonen av et objekt er privat og kun kjent for selve objektet. Dette kan virke som en alvorlig begrensning ved første øyekast. Resultatet er imidlertid modulær og løst koblet kode.

La oss illustrere innkapsling med et annet eksempel. Bilens hastighet måles av bilens internals, men føreren kjenner bilens hastighet ved å se på hastighetsmåleren. Føreren trenger ikke å vite om eller forstå bilens internals for å kjenne bilens hastighet. På samme måte trenger bilens sjåfører ikke å forstå hvordan motorer jobber for å kunne kjøre bilen. Detaljer om hvordan en bil fungerer er skjult fra føreren. Bilens tilstand og oppførsel er skjult fra føreren og er tilgjengelig gjennom bilens grensesnitt (ratt, bremsepedal, dashbord, etc.).

Arv

Et annet kraftig paradigme med objektorientert programmering er klasse arv. Når klasse A er a underklasse av klasse B, arver A klasse attributter og oppførsel av klasse B. Klasse B sies å være foreldreklasse eller overklasse i klasse A. Arvelighet fremmer også kodeåtergjengelighet og modularitet.

Metoder og egenskaper

Metoder er underrutiner knyttet til en klasse, og de definerer oppførselen til en klasse og dens forekomster. Metoden til en klasse har tilgang til internals av en forekomst og kan dermed endre tilstanden til forekomsten. Med andre ord, tilstanden til en forekomst (dvs. instansvariabler) styres av metodene til en forekomst (dvs. forekomst metoder).

På grunn av innkapslingsmønsteret kan ikke instansvariablene av en klasseeksempel åpnes fritt. I stedet blir de tilgjengelige gjennom getters og settere, metoder med det ene formål å få og sette instansvariabler. Egenskaper er en funksjon av Objective-C som gjør etableringen av accessors (getters og setters) trivial. Til tross for brukernes tilgang er det raskt vanskelig å skrive tilgangsmetoder for hver instansvariabel. Vi vil utforske eiendommer mer detaljert senere i denne artikkelen. For nå vurdere egenskaper som wrappers rundt instansvariabler som gjør det lettere å jobbe med forekomstvariabler gjennom getters og setters.


Lære ved eksempel

La oss sette vår kunnskap i praksis ved å lage et nytt Xcode-prosjekt for å jobbe med. Opprett et nytt prosjekt i Xcode ved å velge Nytt> Prosjekt ... fra Fil Meny.

Som vi gjorde i forrige artikkel, velg Kommandolinjeverktøy prosjektmal i applikasjon kategori under OS X seksjon.

Sett Produktnavn til bøker og gi prosjektet et organisasjonsnavn og bedriftsidentifikator. For dette prosjektet er det viktig å sette prosjekttypen til Fundament. Årsaken til dette valget vil bli klart senere i denne artikkelen.

Fortell Xcode hvor du vil lagre prosjektet og klikk på Skape knapp. Du kan legge merke til at prosjektet ser annerledes ut enn prosjektet vi opprettet for å lære C. La oss ta et øyeblikk for å se hva forskjellene er.


prosjekt oversikt

Prosjektet inneholder noen flere filer og mapper enn kommandolinjeverktøyet vi opprettet i forrige artikkel. I tillegg til main.m og Books.1, Det er to nye mapper, Støtter filer og rammer, hver inneholder ett element.

Støtter filer inneholder en fil som heter Bøker-Prefix.pch. De .PCH filtypen forteller oss at dette er en forkompilert headerfil. Dens formål vil bli klart senere i denne serien.

De rammer mappen inneholder rammene som prosjektet er koblet til. Hva er et rammeverk? Et rammeverk er et bunt eller katalog som inneholder et bibliotek, inkludert dets ressurser, for eksempel bilder og headerfiler. Konseptet med en headerfil vil bli klart på bare et minutt. De rammer mappen inneholder for øyeblikket ett element, Foundation.framework.

Mens du oppretter prosjektet, setter du prosjekttypen til Fundament, noe som betyr at prosjektet er knyttet til stiftelsens rammeverk. Stiftelsens rammeverk er et grunnleggende sett med mål-C-klasser. Senere i denne serien vil vi se nærmere på stiftelsens rammeverk.


Opprett en klasse

Det er på tide å lage din første klasse. Når du oppretter en ny fil (Fil> Ny> Fil ... ), presenteres du med en liste over filmaler. Velge kakao fra OS X delen og velg Mål-C klasse mal for å opprette en ny Objective-C klasse. Klikk neste å fortsette.

Gi den nye klassen et navn på Bok og sett sin underklasse til NSObject. Som vi så tidligere, ved å gjøre den nye klassen en underklasse av NSObject, den nye klassen vil arve attributter og oppførsel av NSObject. Dette betyr at den nye Bok klassen får litt funksjonalitet gratis.

Klikk neste å fortsette og fortelle Xcode hvor du vil lagre den nye klassen. Pass på å lagre den nye klassen et sted i ditt Xcode-prosjekt.

Xcode har lagt til to nye filer til prosjektet, Book.h og Book.m. Book.h er headerfilen til Bok klasse og avslører klassegrensesnittet som vi så tidligere. Et klassegrensesnitt inneholder klassens egenskaper og metoder, og det spesifiserer også klassens superklasse. Book.m er implementeringsfilen til klassen og definerer dens oppførsel ved å implementere metodene som er deklarert i klassens headerfil.

Header File

Åpen Book.h og utforske innholdet. Bortsett fra noen kommentarer øverst inneholder headerfilen bare tre linjer med kode. Den første linjen importerer headerfilen til stiftelsens rammeverk. Dette sikrer at Bok klassen har tilgang til klassene og protokollene deklarert i stiftelsens rammeverk.

#importere 

Den andre og tredje linjen danner et par. I Mål-C begynner hvert klassegrensesnitt med @interface og slutter med @slutt, som er begge kompilatordirektiver, det vil si kommandoer eller instruksjoner for kompilatoren. De @interface Direktivet etterfølges av navnet på klassen, et kolon og klassen super-hvis aktuelt. Som vi så tidligere, er foreldreklassen eller superklassen klassen som den arver attributter og atferd.

@interface bok: NSObject @end

NSObject er rotklassen i flertallet av mål-C-klassene. De to første bokstavene, NS, referer til sin opprinnelse, NeXTSTEP, som vi så tidligere i denne artikkelen. Ved å arve fra NSObject, klasser oppfører seg som mål-C-klasser og arver et grunnleggende grensesnitt til runtime-systemet.

Implementeringsfil

Før vi gjør endringer i Bok klasse, la oss ta en rask topp på Book.m, klassens implementeringsfil. I stedet for å importere grunnlagsrammen importerer implementasjonsfilen headerfilen til Bok klasse. Hvorfor er dette nødvendig? Implementeringsfilen må vite hvilke egenskaper og metoder som er deklarert i headerfilen før den kan implementere atferden (dvs. metoder) i klassen. Importoppgaven etterfølges av gjennomføringen av klassen, angitt av @gjennomføring og @slutt.

Legge til egenskaper og metoder

De Bok klassen er ikke veldig nyttig i sin nåværende gjennomføring. Gå over til headerfilen og legg til tre egenskaper år, tittel, og forfatter, og legg til en metode som heter bookInfo.

Egenskaper er deklarert med @eiendom søkeord og kan deklareres hvor som helst i klassen @interface blokkere. De @eiendom Søkeordet etterfølges av typen og navnet på eiendommen. Ikke glem stjernen foran tittel og forfatter egenskaper, fordi et kakaoobjekt alltid refereres til som en peker.

#importere  @interface Book: NSObject @property int år; @property NSString * tittel; @property NSString * forfatter; - (NSString *) bookInfo; @slutt

Metodeangivelsen ligner litt på en funksjonsprototype, men det er en rekke nøkkelforskjeller. Metodeangivelsen starter med et minustegn som indikerer at dette er en instansmetode. Klassemetoder er prefiks med et plustegn. Minustegnet følger etter returmetoden mellom metoden mellom parentes, en forekomst av NSString, og navnet på metoden. Metodeangivelsen slutter med en semikolon.

Jeg er sikker på at du lurer på hva NSString er og hvorfor det må refereres som en peker. De NSString klassen er medlem av stiftelsens rammeverk. Den erklærer grensesnittet for et objekt som styrer en uforanderlig streng. I forrige artikkel så vi at en streng i C kan representeres av en rekke tegn og det er akkurat det som NSString klassen klarer det en rekke tegn under hetten. Fordelen med å bruke NSString er at det gjør det lettere å jobbe med strenge.

implementering bookInfo

Nå som vi har erklært bookInfo metode i klassens headerfil, er det på tide å implementere det i klassens implementeringsfil. Åpen Book.m og legg til følgende kodestykke et sted i @gjennomføring blokkere. Før vi bryter gjennom implementeringen av bookInfo ned, vi må først snakke om objektmeldinger.

- (NSString *) bookInfo NSString * bookInfo = [NSString stringWithFormat: @ "% @ ble skrevet av% @ og publisert i% i" self.title, self.author, self.year]; returnere bookInfo; 

Objektmeldinger

Vi vet allerede at oppførselen til en klasse er definert gjennom sine metoder. For å ringe en metode på et objekt, sendes en melding til objektet. Kontroller følgende kodestykke for å forstå dette konseptet. La oss bryte det ned linje for linje. I den første linjen erklærer vi en ny streng og tilordner den en konstant streng ved å pakke strengen i dobbelt anførselstegn og forutse den med en @ skilt.

NSString * string = @ "Dette er en streng med tegn."; int lengde = [strenglengde]; NSLog (@ "Lengden på strengen er% i. \ N" lengde);

I den andre linjen sender vi en melding om lengde til strengeksemplet. Med andre ord kaller vi metoden lengde på strengeninstansen og metoden returnerer et heltall. Heltallet er tildelt til lengde variabel av type int. I den siste linjen logger vi lengdevariabelen til konsollen ved å ringe NSLog fungere som vi så i forrige artikkel.

Å sende meldinger til objekter er noe du vil gjøre mye, så det er viktig å forstå syntaksen. Selv om syntaksen ser merkelig ut hvis du er ny i Objective-C, er det ikke så vanskelig å forstå. Mellom firkantede parenteser er objektet til venstre og meldings- eller metodenavnet til høyre.

[objektmelding];

Metoder som aksepterer argumenter, ser litt annerledes ut, men den generelle syntaksen er identisk. De NSString klasse, for eksempel, har en annen metode som heter substringFromIndex:. Tykktarmen på slutten av navnet indikerer at denne metoden godtar et argument. Kaller denne metoden på en streng ser slik ut:

NSString * substring = [streng substringFromIndex: 5];

Mål-C er kjent for sine lange og verbose metodenavn. Ta en titt på følgende eksempel, som inneholder et metodenavn med flere argumenter. Du må innrømme at navnet på metoden tydelig sier hva metoden gjør. Metodenavnet er delt inn i biter med hver bit, og aksepterer et argument. Objektmeldinger vil virkelig synke inn når vi begynner å jobbe med iOS SDK.

NSString * anotherString = [strengstrengByPaddingToLength: 5 withString: @ "some string" startingAtIndex: 2];

Før vi går videre, må vi se gjennom implementeringen av bookInfo. Metodimplementeringen starter ved å gjenta metodedeklarasjonen. Den bakre semicolon er erstattet med et par krøllete braces, som vikle rundt implementeringen av metoden. Vi erklærer først en ny streng, bookInfo, og tilordne den en ny streng, opprettet med attributter av vår bokinstans (tittel, forfatter, og år). På slutten av bookInfo metode, vi returnerer den nye strengen, bookInfo, fordi det er hva metoden forventer, en streng som returtype.

Tre ting krever noe avklaring. Først måten stringWithFormat: er en klassemetode og ikke en instansmetode. Vi vet dette fordi metoden kalles på selve klassen, NSString, ikke på en forekomst av klassen. Klassemetoder er vanlige i objektorienterte programmeringsspråk. For det andre er formatet spesifiserer for et objekt representert av @ symbol (foran med prosent-tegn). Både tittel og forfatter er objekter-strenger å være presise. Tredje, den selv- Søkeord refererer alltid til klassens forekomst. I dette tilfellet, selv- refererer til Bok eksempel som metoden bookInfo tilhører.

Tilsynsførere Revisited

Hvis du har jobbet med andre objektorienterte språk, kan tilgangsvariabler i Objective-C være forvirrende. Vi har ikke direkte tilgang til en instansvariabel når vi skriver self.title. Dette er ikke noe mer enn en snarvei for [selv tittel]. Sistnevnte betyr at vi bruker gettermetoden til å spørre forekomsten for instansvariabelen som heter tittel. Det samme gjelder for å sette en instansvariabel. Ta en titt på følgende kodestykke. Som du kan se, bruk av self.title er ikke noe mer enn syntaktisk sukker.

// Denne oppdraget ... self.title = @ "The Hobbit"; // ... tilsvarer ... [self setTitle: @ "The Hobbit"];

id, nil, og NULL

id

Før vi begynner å bruke Bok klasse, jeg vil snakke om noen få søkeord som forvirrer folk fra tid til annen. Når du vil lagre et objekt uten å eksplisitt definere typen av objektet, bruker du id datatype, som også er standardtypen for retur- og argumentdeklarasjoner for mål-C-metoder.

Kraften og nytte av id datatypen går mye lenger, skjønt. De id Datatype er en nøkkelkomponent i Objective-Cs dynamiske skriving og dynamisk binding. Det er viktig å forstå at id Datatypen inneholder ingen informasjon om selve objektet, bortsett fra at det er et objekt.

I Objective-C vet hvert objekt hvilken klasse den tilhører (gjennom en er en variabel) og dette er kritisk. Hvorfor det? En av styrkene til Objective-C er dens dynamiske skriving, noe som betyr at typekontroll utføres ved kjøring i stedet for kompileringstid.

Men siden id datatypen forteller ikke kompilatoren noe om klassen objektet tilhører, objektet selv trenger å gi denne informasjonen til kompilatoren.

Husk at det er helt akseptabelt å statisk skrive et objekt i Objective-C ved å spesifisere spesifikt en objekts klasse i stedet for å bruke id data-type.

Dynamisk Binding

Dette bringer oss til en annen viktig del av Objective-C runtime, dynamisk binding. I Mål-C er en viktig forskjell mellom funksjoner og meldinger at en melding og mottaksobjektet ikke er sammenføyet til kjøretid.

Hva betyr dette og hvorfor er dette viktig? Dette betyr at metoden som påberopes som svar på en melding som sendes til en gjenstand, bestemmes ved kjøretid når både meldingen og objektet er kjent. Dette er det som kalles dynamisk binding.

nil og NULL

I Mål-C, søkeordet nil er definert som a null objekt, det vil si en id med en verdi på 0. Under hetten er det ingen forskjell mellom nil, Nil, og NULL, og det er mulig å sende meldinger til hver av dem uten at et unntak kastes.

Konvensjonen er å bruke nil for gjenstander, Nil for klasser og NULL ellers. Å kunne sende meldinger til nil, Nil, og NULL har fordeler, men det har også ulemper. For mer informasjon om nil, Nil, og NULL, ta en titt på dette spørsmålet om Stack Overflow.


Opprette objekter

Åpen main.m og legg til en importoppgave for å importere headerfilen til Bok klasse. I stedet for å bruke vinkelbeslag, bruker vi doble anførselstegn for å importere headerfilen til Bok klasse. Doble anførselstegn brukes for lokale filer, mens vinkelbeslag brukes til global inkluderer, ved hjelp av prosjektets innfelt sti.

#importere  #import "Book.h"

Umiddelbart under NSLog ring, legg til følgende utdrag for å opprette en forekomst av Bok klasse.

Book * book1 = [[Book alloc] init]; book1.title = @ "The Hobbit"; book1.author = @ "JRR Tolkien"; book1.year = 1937;

I den første linjen erklærer vi en variabel av typen Bok og initialiser den. Dette er et godt eksempel for å illustrere nestede metallsamtaler. Den første metoden ringte på Bok klassen er Alloc. Detaljer om denne anropet er ikke viktige. Gjerningen er at minnet er Allocated for det nye objektet og objektet er opprettet.

På grunn av nesting av samtalene, den i det Metoden kalles på det nye objektet som ble opprettet av Alloc metode. De i det metode i detIaliserer det nye objektet, setter opp objektet og gjør det klart for bruk. De i det Metoden returnerer forekomsten og, i vårt eksempel, tilordner den til book1 variabel.

De neste tre linjene skal være kjent nå, vi setter tittelen, forfatteren og utgivelsesåret til den nye boken.

La oss lage en annen bok og legge begge bøkene til et mål-C-array. Opprettelsen av den andre boken er ikke ny. Den eneste forskjellen er at vi har gjort uttrykkelig bruk av klassens settere for å angi instansvariablene for den nye forekomsten.

Book * book2 = [[Book alloc] init]; [book2 setTitle: @ "The Community of the Ring"]; [book2 setAuthor: @ "JRR Tolkien"]; [book2 setYear: 1954]; NSArray * bøker = [[NSArray alloc] initWithObjects: book1, book2, null];

I den siste linjen oppretter vi en forekomst av NSArray, en annen klasse av stiftelsens rammeverk. De NSArray klassen er en matrise som kan lagre en bestilt liste over objekter. Akkurat som vi gjorde med boksinstansene, allokerer vi minne og initialiserer den nye gruppen.

I stedet for å ringe i det, men vi kaller initWithObjects:initWithObjects: er en utpekt initialiserer, som betyr at det er en i det Metode med noen ekstra klokker og fløyter for å lette objektinitialisering.

initWithObjects: aksepterer et antall objekter du ønsker å lagre i matrisen. Listen over objekter bør alltid ende med nil.

Blanding C og Objective-C

Jeg har allerede nevnt flere ganger at Objective-C er et strengt supersett av C, og at vi fritt kan kombinere C og Objective-C. La oss se hvordan dette virker. Vi starter med å bruke en enkel hvis / annet setning for å sjekke om arrayet inneholder objekter. Ved å sende arrayet en melding av telle, det vil returnere antall gjenstander det inneholder.

Hvis arrayet inneholder objekter, bruker vi en til loop for å iterere over objektene i arrayet. Under hver iterasjon spør vi arrayet for objektet på indeksen Jeg og send objektet - en forekomst av Bok klasse-en melding av bookInfo. Som vi så tidligere, bookInfo returnerer en forekomst av NSString, som vi logger inn på konsollen.

hvis ([bøker teller]> 0) for (int i = 0; i < [books count]; i++)  Book *aBook = [books objectAtIndex:i]; NSLog(@"%@", [aBook bookInfo]);  

Konklusjon

Jeg er sikker på at du er litt overveldet av Objective-C. Dette er normalt. Selv om Objective-C ikke er noe mer enn et tynt lag på toppen av C-språket, går det ganske mye.

Mens det er mer til Objective-C enn diskutert i denne artikkelen, vet du nå det grunnleggende og er klar til å begynne å jobbe med iOS SDK. I neste artikkel vil vi se på iOS SDK og utforske sine ulike komponenter.