Objective-C henter sin objektsynta.fra Smalltalk. Alle syntaksen for ikke-objektorienterede operationer (herunder primitive variabler, forbehandling, udtryk, funktionsdeklarationer og funktionskald) er identiske med C, mens syntaksen for objektorienterede funktioner er en implementering af Smalltalk-stil messaging.
MessagesEdit
Objective-C-modellen for objektorienteret programmering er baseret på besked, der overføres til objektforekomster. I Objective-C kalder man ikke en metode; man sender en besked., Dette er i modsætning til Simula-stil programmering model, der anvendes af C++. Forskellen mellem disse to begreber er i, hvordan den kode, der henvises til af metoden eller meddelelsesnavnet, udføres. På et sprog i Simula-stil er metodenavnet i de fleste tilfælde bundet til et afsnit af kode i målklassen af kompilatoren. I Smalltalk og Objective-C løses målet for en meddelelse ved runtime, hvor det modtagende objekt selv fortolker meddelelsen., En metode identificeres ved hjælp af en vælger eller SEL – en unik identifikator for hvert meddelelsesnavn, ofte kun en NUL-afsluttet streng, der repræsenterer dens navn-og løses til en C-metodepeger, der implementerer den: en IMP. En konsekvens af dette er, at meddelelsesoverførselssystemet ikke har nogen typekontrol. Det objekt, som meddelelsen er rettet mod-modtageren-er ikke garanteret at svare på en meddelelse, og hvis den ikke gør det, rejser den en undtagelse.,
Sender besked metode til det objekt, der peges på med markøren obj ville kræve følgende kode i C++:
obj->method(argument);
I Objective-C, dette er skrevet som følger:
;
Den “metode” opkald er oversat af compileren til objc_msgSend(id selv, SEL op …) familie af runtime funktioner. Forskellige implementeringer håndterer moderne tilføjelser som super. I GNU-familier hedder denne funktion objc_msg_sendv, men den er blevet udskrevet til fordel for et moderne opslagssystem under objc_msg_lookup.,
begge stilarter af programmering har deres styrker og svagheder. Objektorienteret programmering i Simula (C++)-stilen tillader flere arv og hurtigere udførelse ved at bruge kompileringstidsbinding, når det er muligt, men det understøtter ikke dynamisk binding som standard. Det tvinger også alle metoder til at have en tilsvarende implementering, medmindre de er abstrakte. Den Smalltalk – stil programmering som anvendt i Objective – C tillader meddelelser at gå uimplementeret, med metoden løst til dens gennemførelse på runtime., For eksempel kan en meddelelse sendes til en samling objekter, som kun nogle forventes at reagere på uden frygt for at producere runtime-fejl. Meddelelse passerer også kræver ikke, at et objekt defineres på kompileringstidspunktet. En implementering er stadig nødvendig for at metoden skal kaldes i det afledte objekt. (Se afsnittet dynamisk typing nedenfor for flere fordele ved dynamisk (sen) binding.)
Interfaces and implementationsEdit
Objective-C kræver, at grænsefladen og implementeringen af en klasse er i separat deklarerede kodeblokke., Ved konvention placerer udviklere grænsefladen i en headerfil og implementeringen i en kodefil. Headerfilerne, normalt suffi .ed .h, ligner C header filer, mens implementeringen (metode) filer, normalt suffi .ed .m, kan være meget lig C-kode filer.
InterfaceEdit
Dette er analogt med klasseerklæringer som anvendt i andre objektorienterede sprog, såsom C++ eller Python.
grænsefladen af en klasse er normalt defineret i en header fil. En fælles konvention er at navngive headerfilen efter navnet på klassen, f.eks.,h ville indeholde grænsefladen til klassen bolden.
En grænseflade erklæring, der tager form:
I ovenstående, plus tegn betegne klassen metoder, eller metoder, der kan kaldes på klassen selv (ikke på et eksempel), og minus tegn betegne f.eks metoder, som kun kan kaldes på en bestemt instans af klassen. Klassemetoder har heller ikke adgang til instansvariabler.,
koden ovenfor nogenlunde svarer til den følgende C++ interface:
Bemærk, at instanceMethod2With2Parameters:param2_callName: viser interleaving af vælgeren segmenter med argumentet udtryk, for hvilke der ikke er nogen direkte ækvivalent i C/C++.
Tilbage typer kan være nogen standard C-type, en pointer til en generisk Objective-C-objekt, en pointer til en bestemt type objekt, såsom NSArray *, NSImage *, eller NSString *, eller en pointer til den klasse som den metode, der tilhører (instancetype). Standardreturtypen er det generiske Objective-C type id.,
Metodeargumenter Begynd med et navn, der markerer argumentet, der er en del af metodenavnet, efterfulgt af et kolon efterfulgt af den forventede argumenttype i parentes og argumentnavnet. Etiketten kan udelades.
et derivat af grænsefladedefinitionen er kategorien, som gør det muligt at tilføje metoder til eksisterende klasser.
ImplementationEdit
grænsefladen erklærer kun klassegrænsefladen og ikke selve metoderne: den faktiske kode er skrevet i implementeringsfilen., Implementeringsfiler (metode) har normalt filtypen .m
, som oprindeligt betegnede “meddelelser”.
@implementation classname+ (return_type)classMethod { // implementation}- (return_type)instanceMethod { // implementation}@end
metoder skrives ved hjælp af deres grænsefladeerklæringer.Sammenligning af Objective-C og C:
- (int)method:(int)i { return ;}
int function(int i) { return square_root(i);}
syntaks tillader pseudo-navngivning af argumenter.
interne repræsentationer af en metode varierer mellem forskellige implementeringer af Objective-C., Hvis myColor er af klassen farve, instans metode-changeColorToRed:grøn: blå: kan internt mærket _i_Color_changeColorToRed_green_blue. Jeg skal henvise til en instansmetode, med klassen og derefter metodenavne tilføjet og koloner ændret til understregninger. Da rækkefølgen af parametre er en del af metodenavnet, kan den ikke ændres, så den passer til kodningsstil eller udtryk som med ægte navngivne parametre.
imidlertid bruges interne navne på funktionen sjældent direkte. Generelt konverteres meddelelser til funktionsopkald defineret i Objective-C runtime-biblioteket., Det er ikke nødvendigvis kendt på linktidspunktet, hvilken metode der kaldes, fordi modtagerens klasse (objektet, der sendes beskeden) ikke behøver at være kendt før runtime.
InstantiationEdit
Når en Objective-C-klasse er skrevet, kan den instantieres. Dette gøres ved først at tildele en uninitialiseret forekomst af klassen (et objekt) og derefter ved at initialisere det. Et objekt er ikke fuldt funktionsdygtigt, før begge trin er afsluttet., Disse skridt bør udføres med én linje kode, så der er aldrig en allokeret objekt, der ikke har undergået initialisering (og fordi det er uklogt at holde den mellemliggende resultat siden -init
kan vende tilbage til et andet objekt end det, som det kaldes).,
Instantiering med den standard, ikke-parameter startværdi:
MyObject *foo = init];
Instantiering med en brugerdefineret startværdi:
MyObject *foo = initWithString:myString];
I tilfælde, hvor der ikke tilpassede initialiseringen er udført, den “nye” metode kan ofte anvendes i stedet for den alloc-init-beskeder:
MyObject *foo = ;
Også nogle klasser gennemføre klasse metode initializers., Som +new
, de kombinerer +alloc
og -init
, men i modsætning +new
, de vender tilbage en autoreleased eksempel. Nogle klasse metode initializers tage parametre:
MyObject *foo = ;MyObject *bar = ;
alloc besked allokerer hukommelse nok til at holde alle tilfælde variabler for et objekt, sætter alle tilfælde variabler til nul værdier, og vender hukommelsen, i en instans af klassen; på intet tidspunkt under initialiseringen er den hukommelse, der er en instans af superklassen.,
init-meddelelsen udfører instansens opsætning ved oprettelse. Init-metoden skrives ofte som følger:
- (id)init { self = ; if (self) { // perform initialization of object here } return self;}
i ovenstående eksempel skal du bemærke id
returtype. Denne type står for” pointer til ethvert objekt ” i Objective-C (se afsnittet dynamisk indtastning).
initialiizerermønsteret bruges til at sikre, at objektet initialiseres korrekt af dets superklasse, før init-metoden udfører sin initialisering., Det udfører følgende handlinger:
- self = sender superklassen instans en init besked og tildeler resultatet til self (pointer til det aktuelle objekt).
- hvis (selv)kontrollerer, om den returnerede objektpeger er gyldig, før der udføres initialisering.
- returner selvreturnerer værdien af selv til den, der ringer.
en ikke-gyldig objektpeger har værdien nul; betingede udsagn som “hvis” behandler nul som en nullpeger, så initialiseringskoden udføres ikke, hvis den returneres nul., Hvis der er en fejl i initialiseringen, skal init-metoden udføre enhver nødvendig oprydning, herunder at sende en” release ” – meddelelse til sig selv, og returnere nul for at indikere, at initialiseringen mislykkedes. Enhver kontrol for sådanne fejl må kun udføres efter at have kaldt superklassen initialisering for at sikre, at ødelægge objektet vil ske korrekt.
Hvis en klasse har mere end én initialisering metode, kun én af dem (den “udpegede startværdi”) nødt til at følge dette mønster, andre skal kalde det, der er udpeget startværdi i stedet for superklassen startværdi.,
Protokolsedit
i andre programmeringssprog kaldes disse “grænseflader”.
Objective-C blev udvidet ved siden af at introducere begrebet multiple arv af specifikation, men ikke implementering, gennem indførelsen af protokoller. Dette er et mønster, der kan opnås enten som en abstrakt multiple arvet baseklasse i C++ eller som en “grænseflade” (som i Java og C#). Objective – C Gør brug af ad hoc-protokoller kaldet uformelle protokoller og compiler-håndhævede protokoller kaldet formelle protokoller.,
en uformel protokol er en liste over metoder, som en klasse kan vælge at implementere. Det er angivet i dokumentationen, da det ikke har nogen tilstedeværelse på sproget. Uformelle protokoller implementeres som en kategori (se nedenfor) på NSObject og inkluderer ofte valgfrie metoder, som, hvis de implementeres, kan ændre en klasses adfærd. For eksempel kan en tekstfelt klasse have en delegeret, der implementerer en uformel protokol med en valgfri metode til at udføre automatisk færdiggørelse af bruger-indtastet tekst., Tekstfeltet opdager, om delegaten implementerer denne metode (via refleksion), og i bekræftende fald kalder delegatets metode til at understøtte funktionen auto-complete.
en formel protokol ligner en grænseflade i Java, C# og Ada 2005. Det er en liste over metoder, som enhver klasse kan erklære sig for at gennemføre. Versioner af Objective – C før 2.0 krævede, at en klasse skal implementere alle metoder i en protokol, som den erklærer sig selv som vedtagelse; kompilatoren udsender en fejl, hvis klassen ikke implementerer enhver metode fra sine deklarerede protokoller. Mål-C 2.,0 tilføjet støtte til mærkning visse metoder i en protokol valgfri, og compileren vil ikke håndhæve gennemførelsen af valgfrie metoder.
en klasse skal erklæres for at gennemføre denne protokol for at siges at være i overensstemmelse med den. Dette kan påvises ved kørsel. Formelle protokoller kan ikke give nogen implementeringer; de forsikrer simpelthen opkaldere om, at klasser, der er i overensstemmelse med protokollen, vil give implementeringer. I ne .t / Apple-biblioteket bruges protokoller ofte af det distribuerede objektsystem til at repræsentere evnerne for et objekt, der udføres på et fjernsystem.,
syntaksen
@protocol NSLocking- (void)lock;- (void)unlock;@end
angiver, at der er den abstrakte ID.om låsning. Ved angivelse i klassen definition, at protokollen er implementeret,
@interface NSLock : NSObject <NSLocking>// ...@end
i tilfælde af NSLock hævder, at de vil give en implementering for eksempel to metoder.
dynamisk typingEdit
Objective-C, som Smalltalk, kan bruge dynamisk typing: et objekt kan sendes en meddelelse, der ikke er angivet i dens grænseflade., Dette kan give mulighed for øget fleksibilitet, da det giver et objekt mulighed for at “fange” en besked og sende beskeden til et andet objekt, der kan reagere på meddelelsen korrekt, eller ligeledes sende beskeden videre til et andet objekt. Denne adfærd er kendt som besked videresendelse eller delegation (se nedenfor). Alternativt kan en fejlbehandler bruges, hvis meddelelsen ikke kan videresendes. Hvis et objekt ikke videresender en meddelelse, svarer på den eller håndterer en fejl, genererer systemet en runtime-undtagelse., Hvis meddelelser sendes til nul (null object-markøren), ignoreres de lydløst eller hæver en generisk undtagelse, afhængigt af kompilatorindstillinger.
statisk indtastningsinformation kan også eventuelt tilføjes til variabler. Disse oplysninger kontrolleres derefter på kompileringstidspunktet. I de følgende fire udsagn gives stadig mere specifik type information. Udsagnene er ækvivalente ved kørsel, men de ekstra oplysninger gør det muligt for kompilatoren at advare programmereren, hvis det beståede argument ikke stemmer overens med den angivne type.,
- (void)setMyValue:(id)foo;
i ovenstående erklæring kan foo være af enhver klasse.
- (void)setMyValue:(id<NSCopying>)foo;
i ovenstående erklæring kan foo være et eksempel på enhver klasse, der er i overensstemmelse med NSCopying
protokol.
- (void)setMyValue:(NSNumber *)foo;
i ovenstående erklæring skal foo være et eksempel på nsnumber-klassen.
- (void)setMyValue:(NSNumber<NSCopying> *)foo;
i ovenstående erklæring skal foo være et eksempel på nsnumber-klassen, og det skal være i overensstemmelse med NSCopying
protokol.,
i Objective-C er alle objekter repræsenteret som pointers, og statisk initialisering er ikke tilladt. Det enkleste objekt er den type, som id (objc_obj *) peger på, som kun har en isa-pointer, der beskriver sin klasse. Andre typer fra C, som værdier og strukturer, er uændrede, fordi de ikke er en del af objektsystemet. Denne beslutning adskiller sig fra C++ objektmodellen, hvor strukturer og klasser er forenet.
for .ardingedit
Objective-C tillader afsendelse af en meddelelse til et objekt, der muligvis ikke reagerer., I stedet for at svare eller blot droppe beskeden, kan et objekt videresende beskeden til et objekt, der kan svare. Videresendelse kan bruges til at forenkle implementeringen af visse designmønstre, såsom observatørmønsteret eller pro .ymønsteret.
Objective-C runtime angiver et par af metoder, Objekt
Et objekt, der ønsker at gennemføre videresendelse behøver kun at tilsidesætte videresendelse metode med en ny metode til at definere videresendelse adfærd. Handlingsmetoden performv:: behøver ikke tilsidesættes, da denne metode blot udfører en handling baseret på vælgeren og argumenterne., Bemærk SEL
type, som er den type af meddelelser i Objective-C.
Bemærk: i OpenStep, Kakao, og GNUstep, at de almindeligt anvendte rammer for Objective-C kan man ikke bruge det Objekt klassen. Den – (void)for .ardinvocation: (NSInvocation *)eninvocation metode af nsobject klassen bruges til at gøre videresendelse.
Eksempelredit
Her er et eksempel på et program, der demonstrerer det grundlæggende ved videresendelse.speditør.h speditør.m modtager.h
#import <objc/Object.h>// A simple Recipient object.@interface Recipient : Object- (id)hello;@end
Modtager.m
#import "Recipient.h"@implementation Recipient- (id)hello { printf("Recipient says hello!\n"); return self;}@end
main.,m
NotesEdit
når kompilatoren kompileres ved hjælp af gcc, rapporterer kompilatoren:
kompilatoren rapporterer det punkt, der er foretaget tidligere, at for .arder ikke reagerer på hello-meddelelser. Under denne omstændighed er det sikkert at ignorere advarslen, da videresendelse blev implementeret. At køre programmet producerer denne output:
$ ./a.outRecipient says hello!
Kategorieredit
under designet af Objective-C var en af de største bekymringer vedligeholdelsen af store kodebaser., Erfaringer fra den strukturerede programmeringsverden havde vist, at en af de vigtigste måder at forbedre kode på var at opdele den i mindre stykker. Objective – C lånt og udvidet begrebet kategorier fra Smalltalk implementeringer til at hjælpe med denne proces.
desuden tilføjes metoderne inden for en kategori til en klasse ved kørsel. Således tillader kategorier programmøren at tilføje metoder til en eksisterende klasse – en åben klasse – uden behov for at kompilere denne klasse eller endda have adgang til dens kildekode., For eksempel, hvis et system ikke indeholder en stavekontrol i dens Strengimplementering, kan det tilføjes uden at ændre Strengkildekoden.
metoder inden for kategorier kan ikke skelnes fra metoderne i en klasse, når programmet køres. En kategori har fuld adgang til alle instansvariabler i klassen, herunder private variabler.
Hvis en kategori erklærer en metode med samme metodesignatur som en eksisterende metode i en klasse, vedtages kategoriens metode. Således kan Kategorier ikke kun tilføje metoder til en klasse, men også erstatte eksisterende metoder., Denne funktion kan bruges til at rette fejl i andre klasser ved at omskrive deres metoder eller til at forårsage en global ændring af en klasses adfærd i et program. Hvis to kategorier har metoder med samme navn, men forskellige metodesignaturer, er det udefineret, hvilken kategoris metode der er vedtaget.andre sprog har forsøgt at tilføje denne funktion på forskellige måder. TOM tog Objective – C-systemet et skridt videre og tillod også tilsætning af variabler. Andre sprog har brugt prototype-baserede løsninger i stedet, den mest bemærkelsesværdige er selv.
C# og Visual Basic.,NETSPROG implementerer overfladisk lignende funktionalitet i form af udvidelsesmetoder, men disse mangler adgang til klassens private variabler. Ruby og flere andre dynamiske programmeringssprog henviser til teknikken som”monkey patching”.
Logtalk gennemfører en koncept af kategorier (som first-class-enheder), der indordner Objective-C kategorier funktionalitet (Logtalk kategorier kan også bruges som finkornet enheder af sammensætningen, når du definerer fx nye klasser eller prototyper; i særdeleshed en Logtalk kategori, kan det være stort set importeret af en række klasser og prototyper).,
eksempel anvendelse af kategorieredit
dette eksempel opbygger et heltal klasse, ved først at definere en grundlæggende klasse med kun accessor metoder implementeret, og tilføje to kategorier, aritmetik og Display, som udvider den grundlæggende klasse. Mens kategorier kan få adgang til basisklassens private data medlemmer, er det ofte god praksis at få adgang til disse private data medlemmer gennem accessor metoder, som hjælper med at holde kategorier mere uafhængige af basisklassen. Implementering af sådanne accessors er en typisk brug af kategorier. En anden er at bruge kategorier til at tilføje metoder til basisklassen., Det betragtes dog ikke som god praksis at bruge kategorier til underklasse overstyring, også kendt som abe patching. Uformelle protokoller implementeres som en kategori på basen NSObject klasse. Ved konvention vil filer, der indeholder kategorier, der udvider baseklasser, få navnet BaseClass+e .tensionclass.H.
heltal.h
#import <objc/Object.h>@interface Integer : Object { int integer;}- (int)integer;- (id)integer:(int)_integer;@end
heltal.m heltal + aritmetik.h
#import "Integer.h"@interface Integer (Arithmetic)- (id) add: (Integer *) addend;- (id) sub: (Integer *) subtrahend;@end
heltal+aritmetik.m heltal+skærm.h
#import "Integer.h"@interface Integer (Display)- (id) showstars;- (id) showint;@end
heltal+Display.m main.,m
NotesEdit
kompilering udføres for eksempel ved:
gcc -x objective-c main.m Integer.m Integer+Arithmetic.m Integer+Display.m -lobjc
man kan eksperimentere ved at udelade #import “heltal+aritmetik.h ” og linjer og udelade heltal + aritmetik.m i samling. Programmet kører stadig. Dette betyder, at det er muligt at blande og matche tilføjede kategorier, hvis det er nødvendigt; hvis en kategori ikke behøver at have en vis evne, kan den simpelthen ikke kompileres.
PosingEdit
Objective-C tillader en klasse helt at erstatte en anden klasse i et program. Udskiftningsklassen siges at “udgøre” målklassen.,
klasse posering blev erklæret forældet med Mac OS v v10.5, og er ikke tilgængelig i 64-bit runtime. Lignende funktionalitet kan opnås ved at bruge metode s .i..ling i kategorier, der bytter en metodes implementering med en anden, der har samme signatur.
for de versioner, der stadig understøtter posering, modtages alle meddelelser, der sendes til målklassen, i stedet af posingklassen. Der er flere begrænsninger:
- en klasse må kun udgøre en af dens direkte eller indirekte superklasser.,
- den poserende klasse må ikke definere nye instansvariabler, der mangler i målklassen (selvom den kan definere eller tilsidesætte metoder).
- målklassen må ikke have modtaget nogen beskeder før poseringen.
posering, på samme måde med kategorier, tillader global forøgelse af eksisterende klasser. Posering tillader to funktioner fraværende fra kategorier:
- en posing klasse kan kalde tilsidesættede metoder gennem super, og dermed inkorporere implementeringen af målklassen.
- en posing klasse kan tilsidesætte metoder defineret i kategorier.,
for eksempel,
dette opfanger hver påkaldelse af setMainMenu til NSApplication.
#importEdit
på C-sproget medfører #include
præ-kompileringsdirektiv altid, at en fils indhold indsættes i kilden på det tidspunkt. Objective-C har#import
direktiv, tilsvarende bortset fra, at hver fil kun er inkluderet oncen gang pr kompilering enhed, undgå behovet for omfatter vagter.