Mål-C

Mål-C
?
Generell informasjon
Vanlige utvidelser h, m, mm og C
Paradigme objekt orientert
Dukket opp i 1980
Designet av Brad Cox
type system sterk, statisk
implementeringer en rekke
påvirket av C , Småprat
har påvirket Objective-C++ , Java

Objective-C er et objektorientert programmeringsspråk laget som et supersett av C for å implementere en Smalltalk -lignende objektmodell . Den ble opprinnelig laget av Brad Cox og StepStone Corporation i 1980 . I 1988 ble det tatt i bruk som programmeringsspråket NEXTSTEP og i 1992 ble det utgitt under GPL-lisensen for GCC - kompilatoren . Det brukes for tiden som hovedprogrammeringsspråk for Mac OS X , iOS og GNUstep , i tillegg til Swift .

Historikk

På begynnelsen av 1980-tallet ble programvare utviklet ved hjelp av strukturert programmering. Strukturert programmering ble etablert for å hjelpe til med å bryte ned programmer i små deler, noe som gjorde utviklingen enklere når applikasjonen ble veldig stor. Men ettersom problemene fortsatte å vokse over tid, ble strukturert programmering kompleks da noen programmerere rotet seg til å ringe instruksjoner gjentatte ganger, noe som førte til spaghettikode og vanskeliggjorde gjenbruk av kode.

Mange så at objektorientert programmering ville være løsningen på problemet. Faktisk hadde Smalltalk allerede løst mange av disse problemene: noen av de mest komplekse systemene i verden ble drevet av Smalltalk. Men Smalltalk brukte en virtuell maskin, som krevde mye minne for tiden, og var for treg.

Objective-C ble først og fremst skapt av Brad Cox og Tom Love på begynnelsen av 1980-tallet i selskapet deres Stepstone. Begge ble introdusert for Smalltalk mens de var ved ITTs programmeringsteknologisenter i 1981. Cox ble interessert i gjenbruksproblemer i programvareutvikling. Han innså at et språk som Smalltalk ville være avgjørende for å bygge kraftige utviklingsmiljøer for utviklerne ved ITI Corporation. Cox begynte å modifisere C-kompilatoren for å legge til noen av egenskapene til Smalltalk. Han fikk snart en utvidelse for å legge til objektorientert programmering til C som han kalte "OOPC" ( Objektorientert programmering i C ). Love, i mellomtiden, ble ansatt av Shlumberger Research i 1982 og fikk muligheten til å skaffe seg det første eksemplaret av Smalltalk-80, som påvirket stilen hans som programmerer.

For å demonstrere at det ble gjort reelle fremskritt, viste Cox at å gjøre programvarekomponenter virkelig utskiftbare kun krevde mindre endringer i eksisterende verktøy. Spesifikt trengte de å støtte objekter på en fleksibel måte, komme med et sett med biblioteker som var brukbare, og la koden (og eventuelle ressurser som trengs av koden) pakkes i et tverrplattformformat.

Cox og Love grunnla deretter et nytt selskap, Productivity Products International (PPI), for å markedsføre produktet deres, som var en Objective-C-kompilator med et sett kraftige biblioteker.

I 1986 publiserte Cox hovedbeskrivelsen av Objective-C i sin opprinnelige form i boken Object-Oriented Programming, An Evolutionary Approach . Selv om han var nøye med å påpeke at det er mange gjenbruksproblemer som ikke er språkavhengige, ble Objective-C ofte sammenlignet i detalj med andre språk.

Popularisering gjennom NeXT

I 1988 lisensierte NeXT Objective-C fra StepStone (det nye navnet på PPI, Objective-C-merkeeieren) og utvidet GCC -kompilatoren til å støtte Objective-C, samtidig som de utviklet AppKit- og Foundation-bibliotekene. Kit hvor NeXTstep- var basert . Mens NeXT-arbeidsstasjonene ikke klarte å gjøre stor innvirkning på markedet, ble verktøyene mye hyllet i bransjen. Dette førte til at NeXT forlot maskinvareproduksjon og fokuserte på programvareverktøy, og solgte NeXTstep (og OpenStep) som en plattform for tilpasset programmering.

Arbeidet med å utvide GCC ble ledet av Steve Naroff, som begynte i NeXT fra StepStone. Kompilatorendringene ble gjort tilgjengelig under GPL -lisensvilkårene , men ikke kjøretidsbibliotekene, noe som gjorde åpen kildekodebidraget ubrukelig for allmennheten. Dette førte til at andre selskaper utviklet disse bibliotekene under åpen kildekode-lisenser. Senere var Steve Naroff også en viktig bidragsyter til Apples arbeid med å bygge Objective-C Clang -grensesnittet .

GNU -prosjektet begynte arbeidet med sin gratis programvareimplementering av Cocoa, kalt GNUstep og basert på OpenStep-standarden. [ 1 ] Dennis Glatting skrev det første GNU Objective-C runtime - systemet i 1992. GNU Objective-C runtime-systemet, som har vært i bruk siden 1993, er et av de som ble utviklet av Kresten Krab Thorup da han var høyskolestudent i Danmark . Thorup jobbet også i NeXT fra 1993 til 1997.

Apple og Swift utvikling

Etter å ha kjøpt opp NeXT i 1996, brukte Apple OpenStep i sitt nye operativsystem, Mac OS X. Dette inkluderte Objective-C og NeXTs Objective-C-baserte utviklingsverktøy, Project Builder (senere utvidet og nå kjent som Xcode ), samt grensesnittdesignverktøyet Interface Builder. Det meste av Apples nåværende Cocoa API er basert på OneStep-grensesnittobjekter, og det er det mest brukte Objective-C-utviklingsmiljøet for aktiv utvikling.

WWDC 2014 kunngjorde Apple planer om å erstatte Objective-C i kakaoutvikling med det nye Swift -språket , som kalles "Objective-C without the C".

Syntaks

Objective-C består av et veldig tynt lag på toppen av C, og er også et strengt supersett av C . Det vil si at det er mulig å kompilere hvilket som helst program skrevet i C med en Objective-C kompilator, og du kan også fritt inkludere C-kode i en Objective-C klasse.

Det vil si, for å skrive det klassiske "Hello World"-programmet som skal kjøres på konsollen, kan følgende kode brukes:

#import <stdio.h> int main ( int argc , const char * argv [] ) { printf ( "Hei verden \n " ); returner 0 ; }

Koden ovenfor skiller seg fra vanlig C-kode ved den første #import-setningen, som skiller seg fra #include i klassisk C, men funksjonen printf("") er ren C. Objective-Cs egen funksjon for å skrive ut en streng med tegn i konsollen er NSLog(@""); ved å bruke den, ville den forrige koden være som følger:

int main ( int argc , const char * argv [ ] ) { NSLog ( @"Hei verden \n " ); returner 0 ; }

Objective-Cs objektsyntaks stammer fra Smalltalk . All syntaks for ikke-objektorienterte operasjoner (inkludert primitive variabler, forbehandling, uttrykk, funksjonserklæringer og funksjonskall) er identiske med C, mens syntaksen for objektorienterte funksjoner er en lignende implementering som Smalltalk-meldinger.

Meldinger

Objective-Cs objektorienterte programmeringsmodell er basert på å sende meldinger til objektforekomster. Dette er forskjellig fra Simula - stil programmeringsmodellen brukt av C++ , og denne forskjellen er semantisk viktig. I Objective-C kaller man ikke en metode ; man sender en melding , og forskjellen mellom de to konseptene ligger i hvordan koden referert til av meldingen eller metodenavnet blir utført. I et språk i Simula-stil er metodenavnet i de fleste tilfeller bundet til en kodedel i målklassen av kompilatoren, men i Smalltalk og Objective-C er meldingen fortsatt bare et navn, og løses under kjøring: det mottakende objektet har som oppgave å tolke selve meldingen. En konsekvens av dette er at systemmeldingen den sender ikke er typesjekket: objektet som meldingen er adressert til (kjent som mottakeren ) er ikke garantert i seg selv å svare på en melding, og hvis den ikke gjør det, er det ganske enkelt ignorerer det og returnerer en null-peker.

Å sende metodemeldingen til objektet peker på av obj - pekeren vil kreve følgende C++-kode:

obj -> metode ( parameter );

mens i Objective-C ville det bli skrevet som følger:

[ obj metode : parameter ];

Begge programmeringsstilene har sine styrker og svakheter. Simula-style OOP tillater multippel arv og rask utførelse ved bruk av kompileringstidsbinding når det er mulig, men støtter ikke dynamisk binding som standard. Dette tvinger alle metoder til å ha en tilsvarende implementering, med mindre de er virtuelle (en metodeimplementering er fortsatt nødvendig for å foreta anropet). Smalltalk-stil OOP lar meldinger være implementeringsløse - for eksempel kan en hel samling av objekter sende en melding uten frykt for kjøretidsfeil. Sende meldinger krever heller ikke at et objekt defineres på kompileringstidspunktet. (Se avsnittet om dynamisk skriving nedenfor ) for flere fordeler med dynamisk binding.

Det bør imidlertid bemerkes at på grunn av overheaden med å tolke meldinger, tar en melding i Objective-C i beste fall tre ganger så lang tid som et kall til en virtuell metode i C++. [ 2 ]

Grensesnitt og implementeringer

Objective-C krever at grensesnittet og implementeringen av en klasse er i separate kodeblokker. Etter konvensjon legges grensesnittet i en header-fil og implementeringen i en kodefil; header-filer, vanligvis suffikset med .h, ligner på C-header-filer; implementeringsfiler (metode), som vanligvis har .m-suffikset, kan være svært lik C-kodefiler.

Grensesnitt

Klassegrensesnittet er vanligvis definert i overskriftsfilen. En vanlig konvensjon er å navngi overskriftsfilen med samme navn som klassen. Grensesnittet for Klasseklassen skal altså finnes i filen Class.h .

Grensesnitterklæringen til skjemaet:

@grensesnitt klassenavn  : superklassenavn { // forekomstvariabler } + klasseMethod1 ; +( returtype ) klasseMethod2 ; +( return_type ) classMethod3: ( param1_type ) parameter_varName ; -( return_type ) instansMethod1 : ( param1_type ) param1_varName : ( param2_type ) param2_varName ; -( return_type ) instanceMethod2WithParameter: ( param1_type ) param1_varName andOtherParameter: ( param2_type ) param2_varName ; @slutt

Plusstegn angir klassemetoder , minustegn angir instansmetoder . Klassemetoder har ikke tilgang til instansvariabler.

Hvis du kommer fra C++, tilsvarer koden ovenfor noe som dette:

klasse klassenavn : superklassenavn { offentlig : // forekomstvariabler // Klasse (statisk) funksjoner static void * classMethod1 (); statisk returtype klasseMethod2 (); statisk returtype klasseMethod3 ( param1_type parameter_varName ); // Forekomst (medlem) funksjoner return_type instanceMethod1 ( param1_type param1_varName , param2_type param2_varName ); return_type instansMethod2WithParameter ( param1_type param1_varName , param2_type param2_varName = default ) ; };

Merk at den instanceMethod2WithParameterdemonstrerer Objective-Cs parameternavneevne som det ikke er noen direkte ekvivalent for i C/C++.

Returtyper kan være en hvilken som helst standard C-type, en peker til et generisk Objective-C-objekt, eller en peker til en spesifikk type som NSArray *, NSImage * eller NSString *. Standard returtype er den idgeneriske Objective-C-typen.

Metodeargumenter begynner med et kolon etterfulgt av forventet argumenttype i parentes etterfulgt av navnet på argumentet. I noen tilfeller (f.eks. når du skriver system-APIer) er det nyttig å legge til en beskrivende tekst før hver parameter.

-( void ) setRangeStart: ( int ) start End: ( int ) end ; -( void ) importDocumentWithName: ( NSString * ) navn medSpecifiedPreferences: ( Preferences * ) prefs beforePage: ( int ) insertPage ; Implementering

Grensesnittet erklærer bare grensesnittet til klassen og ikke selve metodene; selve koden er skrevet i implementeringen. Implementeringsfiler (metoder) har vanligvis filtypen .m .

@implementeringsklassenavn _ + klasseMethod { // implementering } - instanceMethod { // implementering } @slutt

Metoder er skrevet med deres grensesnittdeklarasjoner. Sammenligning av Objective-C og C:

-( int ) metode: ( int ) i { return [ selv kvadratrot : i ]; } int funksjon ( int i ) { returner kvadratrot ( i ); }

Syntaksen støtter pseudo-navning av argumenter.

-( int ) changeColorToRed: ( float ) rød grønn: ( float ) grønn blå: ( float ) blå [ myColor changeColorToRed : 5,0 grønn : 2,0 blå : 6,0 ];

Den interne representasjonen av denne metoden varierer mellom ulike Objective-C-implementeringer. Hvis myColor er av klassen Color , internt, kan metodeforekomsten -changeColorToRed:green:blue: merkes som _i_Color_changeColorToRed_green_blue . I -en refererer til en metodeforekomst , ledsaget av klasse- og metodenavnene, og kolon erstattes av understrek. Siden rekkefølgen på parameterne er en del av metodenavnet, kan den ikke endres for å passe til kodestilen.

Imidlertid brukes interne funksjonsnavn sjelden direkte, og meldinger blir vanligvis konvertert til funksjonskall definert i Objective-C runtime-biblioteket – metoden som skal kalles er ikke nødvendigvis kjent i bindingstid: mottakerklassen (objektet som sendte melding) trenger ikke å vite om det før kjøretid.

Instantiering

Når en klasse er skrevet i Objective-C, kan den instansieres. Dette gjøres ved først å allokere minne for det nye objektet og deretter initialisere det. Et objekt er ikke fullt funksjonelt før begge trinnene er fullført. Disse trinnene utføres vanligvis med en enkelt kodelinje:

MyObject * o = [[ MyObject alloc ] init ];

Alloc-kallet tildeler nok minne til å holde alle instansvariablene for et objekt, og init-kallet kan overstyres for å sette instansvariablene til spesifikke verdier ved opprettelsestidspunktet. Init-metoden er ofte skrevet som følger:

-( id ) init { self = [ super init ]; if ( selv ) { ivar1 = ''' verdi1 ''' ; ivar2 = verdi2 ; . . . } returnere selv ; }

Objective-C ble utvidet i NeXT for å introdusere konseptet multippel arv fra spesifikasjonen, men ikke implementeringen, gjennom introduksjonen av protokoller . Dette er en levedyktig modell, enten som en multi-arvet abstrakt baseklasse i C++, eller som et "grensesnitt" (som i Java eller C# ). Objective-C benytter seg av ad-hoc-protokoller, kalt uformelle protokoller , og kompilatoren må følge såkalte formelle protokoller .

Dynamisk skriving

Objective-C, som Smalltalk, kan bruke dynamisk skriving : et objekt kan motta en melding som ikke er spesifisert i grensesnittet. Dette er tillatt for å øke fleksibiliteten, siden det lar et objekt "fange" en melding og sende den til et annet objekt som kan svare på den meldingen på riktig måte, eller på lignende måte videresende meldingen til et annet objekt. Denne oppførselen er kjent som videresending eller delegering av meldinger (se nedenfor). Alternativt kan en feilbehandler brukes i tilfelle meldingen ikke kan videresendes. Hvis et objekt ikke videresender en melding, svarer på den eller håndterer en feil, vil systemet gi et unntak under kjøring. Hvis meldinger sendes til null (null-objektpekeren), vil de bli ignorert stille eller gi et generisk unntak, avhengig av kompilatoralternativer.

Statisk skrevet informasjon kan eventuelt legges til variabler. Denne informasjonen blir deretter sjekket på kompileringstidspunktet. Stadig mer spesifikke typer informasjon er gitt i de neste fire uttalelsene. Disse erklæringene er ekvivalente ved kjøretid, men tilleggsinformasjonen lar kompilatoren advare programmereren hvis det beståtte argumentet ikke samsvarer med den angitte typen.

- ( void ) setMyValue: ( id ) foo ;

I erklæringen ovenfor kan foo være av hvilken som helst klasse.

- ( void ) setMyValue: ( id < NSCopying > ) foo ;

I erklæringen ovenfor kan foo være en forekomst av en hvilken som helst klasse som tilfredsstiller NSCopying- protokollen .

- ( void ) setMyValue: ( NSNumber * ) foo ;

I erklæringen ovenfor må foo være en forekomst av NSNumber -klassen .

- ( void ) setMyValue: ( NSNumber < NSCopying > * ) foo ;

I erklæringen ovenfor må foo være en forekomst av NSNumber -klassen , og må tilfredsstille NSCopying- protokollen .

Videresending

Objective-C lar deg sende en melding til et objekt som kanskje ikke svarer. I stedet for å svare eller bare ignorere meldingen, kan et objekt videresende meldingen til et annet objekt som kan svare på den. Videresending kan brukes til å forenkle implementeringen av visse designmønstre , for eksempel observatør eller proxy .

Objective-C runtime spesifiserer et par metoder i Object:

  • videresendingsmetoder:
- ( retval_t ) forward: ( SEL ) sel args: ( arglist_t ) args ; // med GCC - ( id ) forward: ( SEL ) sel args: ( marg_list ) args ; // med NeXT/Apple-systemer
  • handlingsmetoder:
- ( retval_t ) performv: ( SEL ) sel args: ( arglist_t ) args ; // med GCC - ( id ) performV: ( SEL ) sel args ( marg_list ) args ; // med NeXT/Apple-systemer

Et objekt som ønsker å implementere videresending trenger bare å overstyre videresendingsmetoden med en ny metode som definerer fremadrettet virkemåte. Handlingsmetoden performv::trenger ikke å overstyres, da denne metoden bare utfører en handling basert på velgeren og argumentene. Typen SELer typen meldinger i Objective-C.

Merk: I openStep, Cocoa og GNUstep, de ofte brukte Objective-C-arbeidsområdene, trenger du ikke bruke Object. klassemetoden - (void)forwardInvocation:(NSInvocation *)anInvocationbrukes NSObjecttil å utføre videresendingen.

Eksempel

Her er et eksempel på et program som demonstrerer det grunnleggende om videresending.

Speditør.h # import <objc/Object.h> @interface Forwarder  : Objekt { id- mottaker ; // Objektet vi ønsker å videresende meldingen til. } // Accessor methods - ( id ) mottaker ; - ( id ) setRecipient: ( id ) _recipient ; @slutt Speditør.m # import "Forwarder.h" @implementation Forwarder - ( retval_t ) forward: ( SEL ) sel args: ( arglist_t ) args { /* * Sjekk om mottakeren svarer på meldingen. * Dette kan være ønskelig eller ikke, for eksempel hvis en mottaker * ikke svarer på meldingen i sin tur, kan den sende den på nytt. */ if ([ mottaker svarerToVelger : sel ]) { return [ recipient performv : sel args : args ]; } annet { return [ self error : "Mottakeren svarer ikke" ]; } } - ( id ) setRecipient: ( id ) _recipient { [ mottaker autorelease ]; container = [ _mottaker beholde ]; returnere selv ; } - ( id ) mottaker { retur mottaker ; } @slutt Mottaker.h # import <objc/Object.h> // Et enkelt mottaksobjekt. @grensesnitt Mottaker  : Objekt - ( id ) hei ; @slutt Mottaker.m # import "Recipient.h" @implementation Mottaker - ( id ) hei { printf ( "Mottakeren sier hei! \n " ); returnere selv ; } @slutt hoved.m # import "Forwarder.h" # import "Recipient.h" int main ( void ) { Forwarder * forwarder = [ Forwarder new ]; Mottaker * mottaker = [ Mottaker ny ]; [ videresettRecipient : mottaker ] ; // Velg mottaker. /* * Se at avsender ikke svarer på hilsenen! Det vil bli videresendt. * Alle ukjente metoder vil bli videresendt til mottakeren * (hvis mottakeren svarer på dem, som fortalt i videresendingen) */ [ speditør hei ]; [ mottakerfrigivelse ] ; [ speditørfrigivelse ] ; returner 0 ; } Notater

Når kompileringen er kompilert med gcc , rapporterer kompilatoren:

$ gcc -x objektiv-c -Wno-import Forwarder.m Mottaker.m main.m -lobjc

main.m: I funksjon 'main':

main.m:12: advarsel: 'Forwarder' svarer ikke på 'hei'

$

Kompilatoren rapporterer som kommentert tidligere, at den ikke svarer på hei-Forwarder meldinger . I denne omstendigheten er det trygt å ignorere advarselen siden videresending ble implementert. Å kjøre programmet produserer denne utgangen:

& ./a.ut

Mottakeren sier hei!

Språkvarianter

Objective-C++

Objective-C++ er en språkvariant som støttes av GNU Compiler Collection -grensesnittet og Clang , som kan kompilere kildekodefiler som bruker en kombinasjon av C++ og Objective-C-syntaks. Objective-C++ legger til C++ utvidelsene som Objective-C legger til C. Siden ingenting er gjort for å forene semantikken bak funksjonene til forskjellige språk, finnes det visse begrensninger:

  • En C++-klasse kan ikke avledes fra en Objective-C-klasse og omvendt.
  • C++-navneområder kan ikke deklareres i en Objective-C-deklarasjon.
  • Objective-C erklæringer må vises globalt, ikke innenfor en C++ erklæring.
  • Objective-C-klasser kan ikke ha variable forekomster av C++-klasser som ikke har en standardkonstruktør eller har en eller flere virtuelle metoder, men pekere til C++-objekter kan brukes som variable forekomster uten begrensning (de er tilordnet i -init-metoden).
  • "etter verdi"-semantikken til C++ kan ikke brukes på Objective-C-objekter, som kun er tilgjengelige via pekere.
  • En Objective-C-erklæring kan ikke være inne i en C++-erklæringsmal og omvendt. Imidlertid kan Objective-C-typer (som Classname * ) brukes som C++-malparametere.
  • Objective-C og C++ unntakshåndtering er forskjellig; hvert språk kan bare håndtere sine egne unntak. Dette reduseres i nyere versjoner ved enten å erstatte Objective-C-unntak fullstendig med C++-unntak (som Apple gjør), eller delvis ved å koble Objective-C++-biblioteket (GNUstep libobjc2).
  • Vær forsiktig siden Objective-C og C++ runtime exception destructor kall ikke samsvarer (for eksempel vil en C++ destructor ikke bli kalt når et Objective-C unntak går utenfor omfanget av et C++ objekt). C++). Nyere 64-biters versjoner adresserer dette ved å introdusere interoperabilitet med C++-unntak i denne forbindelse. [ 3 ]
  • Objective-C-blokker og C++11-lambdaer er forskjellige enheter, men en blokk genereres transparent på Mac OS X når en lambda passeres der en blokk forventes. [ 4 ]

Objective-C 2.0

Worldwide Developers Conference i 2006 kunngjorde Apple utgivelsen av "Objective-C 2.0", en revisjon av Objective-C-språket som inkluderer "moderne søppelinnsamling, syntaksforbedringer, [ 5 ] utførelsesforbedringer [ 6 ]​ og 64-biters Brukerstøtte". Mac OS X v10.5 , utgitt i oktober 2007, inkluderte en Objective-C 2.0-kompilator. GCC 4.6 støtter mange nye Objective-C-applikasjoner, for eksempel deklarerte og syntetiserte egenskaper, punktsyntaks, rask opptelling, valgfrie protokollmetoder, metode/protokoll/klasseattributter, klasseutvidelser og en ny GNUnn Objective-C API. [ 7 ]

Søppelinnsamling

Mål 2.0 hadde en valgfri konservativ søppeloppsamler . Når den kjørte i bakoverkompatibilitetsmodus , endret den referansetellingsoperasjoner som "hold" og "slipp" til NOPs ( No Operations , en assembler-instruksjon som indikerer at prosessoren ikke trenger å gjøre noe). Alle gjenstander ble sendt til søppelsamleren da søppelhenting var aktivert. C-pekere kan kvalifiseres med "__strong" for å få kompilatoren til å avskjære skrivinger og dermed delta i søppelinnsamling. [ 8 ] Et svakt nullstillingsundersystem ble også tilveiebrakt slik at pekere merket "__weak" ble nullstilt når objektet (eller mer enkelt, søppelsamlerens minne) ble samlet. Søppelsamleren fantes ikke i Objective-C 2.0-implementeringen av iOS. [ 9 ] Søppelinnsamling i Objective-C kjører på en lavprioritert tråd og kan stoppe brukerhendelser, med den hensikt å holde brukeropplevelsen responsiv. [ 10 ]

Søppelinnsamling var aldri tilgjengelig på iOS på grunn av ytelsesproblemer. Den ble avviklet i versjon 10.8 av OS X til fordel for Automatic Reference Counting (ARC) og skal etter planen fjernes i en fremtidig versjon av OS X. [ 11 ] Objective-C i iOS 7 utført på ARM64 bruker 19 bits av en 64 -bitord for å lagre referanseantallet, som en form for merket peker. [ 12 ] ​[ 13 ]

Egenskaper

Objective 2.0 introduserer en ny syntaks for å deklarere instansvariabler som egenskaper, med valgfrie attributter for å konfigurere generering av aksessormetoder. Egenskaper er på en måte offentlige instansvariabler; det vil si at å erklære en forekomstvariabel som en egenskap gir eksterne klasser tilgang (muligens begrenset, for eksempel skrivebeskyttet ) til den egenskapen. En egenskap kan erklæres som "skrivebeskyttet" og kan leveres med lagringssemantikk som "tilordne" , "kopi" eller "behold " . Som standard anses egenskaper som atomiske, noe som resulterer i en lås for å forhindre at flere tråder får tilgang til den samtidig. En eiendom kan erklæres "nonatomic" , noe som fjerner denne forsikringen.

@interface Person  : NSObject { @offentlig NString * navn ; @privat int alder ; } @property ( kopi ) NSString * navn ; @property ( skrivebeskyttet ) int alder ; -( id ) startWithAge: ( int ) alder ; @slutt

Egenskaper implementeres via nøkkelordet @synthesize, som genererer getter (og setter, hvis ikke skrivebeskyttet) metoder i henhold til egenskapserklæringen. Alternativt må getter- og settermetodene implementeres eksplisitt, eller @dynamic-nøkkelordet kan brukes for å indikere at tilgangsmetodene må leveres på andre måter. Når de kompileres med Clang 3.1 eller høyere, vil alle egenskaper som ikke er eksplisitt deklarert med @dynamic, ikke er sjekket readonlyeller ikke har fullstendige brukerimplementerte metoder getterog setterautomatisk bli @synthesizeimplisitt deklarert.

@implementeringsperson _ @synthesize navn ; -( id ) startWithAge: ( int ) startAge { self = [ superinitial ] ; if ( selv ) { alder = startAlder ; // MERK: direkte tilordning av instansvariabelen, ikke setter-egenskapen } returnere selv ; } -( int ) alder { retur alder ; } @slutt

Egenskaper kan nås ved hjelp av tradisjonell meldingsoverførselssyntaks, stiplet notasjon eller, i nøkkelverdikoding, via valueForKey:/ -metodene setValue:forKey.

Person * aPerson = [[ Person alloc ] startWithAge : 53 ]; en person . navn = @"Steve" ; // MERK: punktnotasjon bruker den syntetiserte setteren, // tilsvarende [aPerson setName: @"Steve"]; NSLog ( @"Tilgang via melding (%@), punktnotasjon (%@ ) , egenskapsnavn ( % @ ) og instansvariabel direkte tilgang ( % @ ) " , [ aPerson name ] , aPerson . name , [ aPerson valueForKey : @"navn" ], aPerson -> navn );

For at bruk av punktnotasjon skal kunne påkalle tilgangsegenskaper på en instansmetode, må nøkkelordet "selv" brukes:

-( void ) introduceMeWithProperties: ( BOOL ) useGetter { NSLog ( @"Hei, mitt navn er %@." , ( useGetter ? self . name : name )); // MERK: getter vs. ivar tilgang }

En klasse eller protokollegenskaper kan introspiseres dynamisk.

int jeg ; int propertycounter = 0 ; objc_property_t * propertyList = copyPropertyList_class ([ aPerson class ], & propertyCount ); for ( i = 0 ; i < propertiesCounter ; i ++ ) { objc_property_t * thisProperty = eiendomsliste + i ; const char * eiendomsnavn = eiendom_getNavn ( * denneProperty ); NSLog ( @"Personen har en egenskap: '%s'" , egenskapsnavn ); } Ikke-skjøre forekomstvariabler

Objective-C 2.0 gir ikke-skjøre forekomstvariabler som støttes av kjøretidsmiljøet (for eksempel å lage kode for 64-bit Mac OS X samt kode for alle iOS). Under den moderne kjøretiden legges et ekstra lag med skjevhet til for å instansiere tilgangsvariabler, slik at den dynamiske linkeren kan justere instansieringsplanet under kjøring. Denne egenskapen muliggjør to store forbedringer av Objective-C-koden:

  • Eliminerer problemet med sprø binære grensesnitt - superklasser kan endre størrelse uten å påvirke binær kompatibilitet.
  • Den lar forekomstvariabler som gir bakoverkompatibilitet for egenskaper syntetiseres under kjøring uten å bli deklarert i klassegrensesnittet.
Rask oppregning

I stedet for å bruke et NSEnumerator-objekt eller indikere iterasjon gjennom en samling, tilbyr Objective-C 2.0 den raske opptellingssyntaksen. I Objective-C 2.0 er følgende løkker funksjonelt likeverdige, men har forskjellige ytelsesegenskaper.

// Bruke NSEnumerator NSEnumerator * enumerator = [ thePeople objectEnumerator ]; Person * p ; while (( p = [ enumerator nextObject ]) != null ) { NSLog ( @"%@ er %i år gammel." , [ p navn ] , [ side ]); } // Bruke indekser for ( int i = 0 ; i < [ thePeople count ]; i ++ ) { Person * p = [ People objectAtIndex : i ] ; NSLog ( @"%@ er %i år gammel." , [ p navn ] , [ side ]); } // Bruke rask opptelling for ( Person * p i People ) { NSLog ( @"%@ er %i år gammel." , [ p navn ] , [ side ]); }

Rask opptelling genererer mer effektiv kode enn standard opptelling fordi metodekall for å telle opp objekter erstattes av pekeraritmetikk ved bruk av NSFastEnumeration-protokollen.

Klasseutvidelse

En klasseutvidelse har samme syntaks som en kategorierklæring uten et kategorinavn, og metodene og egenskapene som er deklarert i den, legges direkte til klassen main. Det brukes mest som et alternativ til en kategori for å legge til metoder til en klasse uten å deklarere dem i de offentlige overskriftene, med fordelen at for klasseutvidelser kontrollerer kompilatoren at alle privat erklærte metoder faktisk er implementert. [ 7 ]

Blokkerer

Blocks er en ikke-standard utvidelse til Objective-C (samt C og C++ ) som bruker en spesiell syntaks for å lage nedleggelser . Blocks støttes kun på Mac OS X 10.6 "Snow Leopard" eller høyere og iOS 4 eller høyere, samt GNUstep med libobjc2 1.7 og kompilert med Clang 3.1 eller høyere. [ 14 ]

#include <stdio.h> #include <Block.h> typedef int ( ^ IntBlock )(); IntBlock MakeCounter ( int start , int increment ) { __block int i = start ; return Block_copy ( ^ { int ret = i ; i += øker ; returnere ret ; }); } int main ( void ) { IntBlock mycounter = MakeCounter ( 5 , 2 ); printf ( "Første anrop: %d \n " , min teller ()); printf ( "Andre anrop: %d \n " , min teller ()); printf ( "Tredje anrop: %d \n " , min teller ()); /* fordi den ble kopiert, må den også frigis */ block_release ( mycounter ); returner 0 ; } /* Utgang: Første anrop: 5 Andre anrop: 7 Tredje anrop: 9 */

Modern Objective-C

Automatisk referansetelling

Automatic Reference Counting ( ARC ) er en kompileringstidsfunksjon som eliminerer behovet for programmerere å manuelt lagre tellinger ved å bruke retainog release. [ 11 ] I motsetning til søppelsamleren , som fungerer under kjøring, fjerner ARC overheaden til en separat prosess som administrerer kontooppbevaring. ARC og manuell minnebehandling utelukker ikke hverandre; utviklere kan fortsette å bruke ikke-ARC-kode i prosjekter som har ARC aktivert ved å deaktivere ARC for individuell kildekode. Xcode kan også prøve å automatisk oppgradere et prosjekt til ARC.

Bokstaver

Runtimene for NeXT og Apple Obj-C for lenge siden inkluderte en snarvei for å lage nye strenger ved å bruke bokstavelig syntaks, @"una nueva cadena"og også droppet CoreFoundation-konstanter kCFBooleanTrueog boolske kCFBooleanFalsevariabelverdier NSNUmber. Bruk av dette formatet frigjør programmereren fra å bruke de lengste initWithStringeller lignende metodene når han utfører visse operasjoner.

Når du bruker Apples LLVM 4.0 eller høyere kompilator, kan arrays, ordbøker og tall (klassene NSArayog ) NSDictionaryogså NSNumberopprettes ved hjelp av bokstavelig syntaks i stedet for metoder. [ 15 ]​ Den bokstavelige syntaksen bruker henholdsvis symbolet @kombinert med []eller {}for ()å lage klassene nevnt ovenfor. [ 16 ]

Eksempel uten bokstaver:

NSArray * myVector = [ NSArray arrayWithObjects : objekt1 , objekt2 , objekt3 , null ]; NDictionary * myDictionary1 = [ NDictionary dictionaryWithObject : anObject forKey : @"key" ]; NDictionary * myDictionary2 = [ NSDictionary dictionaryWithObjectsAndKeys : objekt1 , nøkkel1 , objekt2 , nøkkel2 , null ]; NSNumber * myNumber = [ NSNumber numberWithInt : myInt ]; NSNumber * myNumberSum = [ NSNumber numberWithInt :( 2 + 3 )]; NSNumber * myBooleanNumber = [ NSNumber numberWithBoolean : YES ];

Eksempel med bokstaver:

NSArray * myVector = @[ objekt1 , objekt2 , objekt3 ] ; NSDictionary * myDictionary1 = { @"nøkkel" : anObject }; NDictionary * myDictionary2 = { key1 : object1 , key2 : object2 }; NSNumber * myNumber = @{ myInt } ; NSNumber * myNumberSum = @{ 2 + 3 } ; NSNumber * myBooleanNumber = @YES ;

Imidlertid, i motsetning til strengliteraler som er kompilert som konstanter i den kjørbare, er disse literalene kompilert som kode tilsvarende metodekallene nevnt ovenfor. Spesielt ved manuell håndtering av minnereferansetelling er disse objektene selvfrie, noe som krever spesiell forsiktighet når de for eksempel brukes med statiske funksjonsvariabler eller andre typer globale variabler.

Abonnementer

Når du bruker Apples LLVM 4.0 eller høyere kompilator, kan matriser og ordbøker ( klassene NSArrayog NSDictionary) manipuleres ved hjelp av abonnenter. [ 15 ] Subscripts kan brukes til å hente verdier fra indekser (vektorer) eller nøkler (ordbøker), og med mutable objekter kan du også bruke dem til å sette objekter til indekser eller nøkler. I koden er subscripts representert ved hjelp av firkantede parenteser [ ]. [ 16 ]

Eksempler uten abonnement:

id objekt1 = [ aVector objectAtIndex : 0 ]; id objekt2 = [ aDictionary objectForKey : @"nøkkel" ]; [ aVectorMutable replaceObjectAtIndex : 0 withObject : object3 ]; [ aMutableDictionary setObject : objekt4 forKey : @"nøkkel" ];

Eksempler med abonnementer:

id objekt1 = aVektor [ 0 ]; id objekt2 = aDictionary [ @"nøkkel" ]; aMutableVector [ 0 ] = objekt3 ; aMutableDictionary [ @"nøkkel" ] = objekt4 ;

"Moderne" Objective-C Syntax (1997)

Etter Apples kjøp av NeXT ble det gjort flere forsøk på å gjøre språket mer likt andre eksisterende språk. Et slikt forsøk var introduksjonen av det som på den tiden ble kalt "Modern Syntax" for Objective-C (i motsetning til den eksisterende "klassiske" syntaksen). Det var ingen endring i faktisk oppførsel, det var bare en alternativ syntaks. Å påkalle en metode ble gjort slik:

objekt = ( MyClass . alloc ). start ; objekt . firstTag ( param1 , param2 );

Og det var tilfeldigvis skrevet på denne andre måten:

objekt = [[ MyClass alloc ] init ]; [ objekt firstLabel : param1 secondLabel : param2 ];

Tilsvarende gikk erklæringene fra å være slik:

-( void ) firstLabel ( int param1 , int param2 );

å være slik:

-( void ) firstTag: ( int ) param1 secondTag: ( int ) param2 ;

Denne "moderne" syntaksen støttes ikke i nåværende Objective-C-dialekter.

Portable Object Compiler

I tillegg til GCC / NeXT / Apple -implementeringene , som la til forskjellige utvidelser til den originale Stepstone-implementeringen, er det også en annen gratis og åpen implementering av Objective-C kalt Protable Object Compiler. [ 17 ] Settet med utvidelser implementert av Portable Object Compiler skiller seg fra GCC/NeXT/Apple-implementeringene; spesielt inkluderer den Smalltalk -lignende blokker for Objective-C, mens den mangler protokoller og kategorier, to funksjoner som er mye brukt i OpenStep og dets derivater. Til sammen representerer POC et eldre, pre-NeXT stadium av språkevolusjon, akkurat ifølge Brad Cox sin bok fra 1991.

Det inkluderer også et kjøretidsbibliotek kalt ObjectPak, som er basert på Cox sitt originale ICPak101-bibliotek (som selv stammer fra Smalltalk-80-klassebiblioteket) og er radikalt forskjellig fra OneStep FoundationKit.

GEOS Objective-C

PC GEOS-systemet brukte et programmeringsspråk kjent som GEOS Objective-C eller goc ; [ 18 ] Til tross for deres lignende navn, er de to språkene like i det overordnede konseptet og i bruken av nøkkelord innledet med @-tegnet.

Klang

Clang - kompilatorpakken , en del av LLVM -prosjektet , implementerer Objective-C så vel som andre språk.

Se også

Referanser

  1. "Introduksjon til GNUstep" (på engelsk) . Hentet 10. juli 2014 . 
  2. ^ "Sammenligning av ytelse av vanlige operasjoner" . Arkivert fra originalen 1. juli 2009 . Hentet 19. juni 2019 . 
  3. "Bruke C++ med Objective-C " . 19. november 2008. Arkivert fra originalen 31. desember 2008 . Hentet 10. juli 2014 . 
  4. "Clang 3.5-dokumentasjon - Interoperabilitet med C++11 lambdas " . Hentet 10. juli 2014 . 
  5. Dave Vasilevsky (10. august 2006). "Objective-C 2.0: flere ledetråder " . Arkivert fra originalen 18. juni 2009 . Hentet 10. juli 2014 . 
  6. ^ Dietmar Planitzer (9. august 2006). "Re: Objective-C 2.0" (på engelsk) . Arkivert fra originalen 24. november 2010 . Hentet 10. juli 2014 . 
  7. a b "GCC 4.6-serieutgivelse: Endringer, nye funksjoner og rettelser " . Hentet 10. juli 2014 . 
  8. Apple . Garbage Collector API . Hentet 10. juli 2014 . 
  9. Apple . "Introduksjon til søppelsamleren " . Hentet 10. juli 2014 . 
  10. Apple (6. november 2007). "Leopard-teknologi for utviklere: Sammendrag av Objective-C 2.0 " . Arkivert fra originalen 24. juli 2010 . Hentet 10. juli 2014 . 
  11. a b Apple (17. juli 2012). ARC Transition Notes . Hentet 10. juli 2014 . 
  12. Mike Ash (27. september 2013). "ARM64 og deg" (på engelsk) . Hentet 10. juli 2014 . 
  13. SealieSoftware.com (24. september 2013). "Objective-C forklarte: ISA er ikke en peker " . Hentet 10. juli 2014 . 
  14. Apple (8. mars 2011). "Programmering i blokker" (på engelsk) . Hentet 10. juli 2014 . 
  15. a b Apple . "Programmering med Objective-C: Verdier og samlinger " . Hentet 10. juli 2014 . 
  16. a b Klang . Objekt-C bokstaver . Hentet 10. juli 2014 . 
  17. "Bærbar objektkompilator " . Hentet 10. juli 2014 . 
  18. ^ "GEOS SDK " . Hentet 10. juli 2014 . 

Eksterne lenker