Objective-C származik az objektum szintaxisa Smalltalk. A nem objektumorientált műveletek szintaxisa (beleértve a primitív változókat, az előfeldolgozást, a kifejezéseket, a függvénynyilatkozatokat és a függvényhívásokat) megegyezik a C szintaxisával, míg az objektumorientált funkciók szintaxisa a Smalltalk stílusú üzenetküldés megvalósítása.
MessagesEdit
az objektumorientált programozás objektív-C modellje az objektumpéldányokra továbbított üzeneteken alapul. Az Objective-C-ben az egyik nem hív egy módszert; az egyik üzenetet küld., Ez ellentétben áll a C++által használt Simula-stílusú programozási modellel. A két fogalom közötti különbség abban rejlik, hogy a módszerrel vagy az üzenet nevével hivatkozott kódot hogyan hajtják végre. Simula-stílusú nyelven a módszer neve a legtöbb esetben a fordító által a célosztály kódrészletéhez van kötve. A Smalltalk-ban és az Objective-C-ben az üzenet célpontja futásidőben oldódik meg, a fogadó objektum maga értelmezi az üzenetet., A metódust egy választó vagy SEL azonosítja — minden egyes üzenetnév egyedi azonosítója, gyakran csak a nevét ábrázoló NUL-végződésű karakterlánc -, és egy C metódusmutatóra oldja fel: egy IMP-re. Ennek következménye, hogy az üzenetátadó rendszernek nincs típusellenőrzése. Az objektum, amelyre az üzenet irányul — a Vevő — nem garantálja, hogy válaszol egy üzenetre, ha nem, kivételt vet fel.,
Küldés, az üzenet a módszer, hogy a tárgy által mutatott a mutató obj lenne szükség, a következő kódot, a C++:
obj->method(argument);
Az objective-C, ez van írva az alábbiak szerint:
;
A “módszer” hívás fordította a fordító, hogy a objc_msgSend(id egyéni, SEL op …) futásidejű függvénycsalád. A különböző megvalósítások olyan modern kiegészítéseket kezelnek, mint a super. A GNU családokban ezt a funkciót objc_msg_sendv-nek hívják, de elavult egy modern keresési rendszer javára az objc_msg_lookup alatt.,
mindkét programozási stílusnak megvannak az erősségei és gyengeségei. A simula (C++) stílusú objektumorientált programozás lehetővé teszi a többszörös öröklést és a gyorsabb végrehajtást a fordítási idejű kötés használatával, amikor csak lehetséges, de alapértelmezés szerint nem támogatja a dinamikus kötést. Arra is kényszeríti az összes módszert, hogy megfelelő végrehajtással rendelkezzen, kivéve, ha elvontak. Az Objective-C-ben használt Smalltalk-stílusú programozás lehetővé teszi, hogy az üzenetek nem valósuljanak meg, a módszer futási időben történő végrehajtására megoldódott., Például egy üzenet küldhető egy objektumgyűjteménybe, amelyre csak néhányan fognak válaszolni, anélkül, hogy félnének a futási hibák előállításától. Az üzenet átadása szintén nem követeli meg, hogy egy objektumot fordítási időben definiáljanak. Még mindig szükség van egy megvalósításra ahhoz, hogy a módszert meghívják a származtatott objektumba. (Lásd az alábbi dinamikus gépelési szakaszt a dinamikus (késői) kötés további előnyeiről.)
interfészek és implementációkszerkesztés
Objective-C megköveteli, hogy egy osztály interfésze és implementációja külön deklarált kódblokkokban legyen., A fejlesztők általában egy fejlécfájlba helyezik az interfészt,a megvalósítást pedig egy kódfájlba. A fejlécfájlok általában elegendőek .h, hasonlóak a C fejléc fájlokat, míg a végrehajtás (módszer) fájlok, általában utótag .m, nagyon hasonló lehet A C kódfájlokhoz.
InterfaceEdit
Ez hasonló az osztály deklarációkhoz, mint más objektumorientált nyelvekben, például a C++ vagy a Python.
egy osztály interfészét általában egy fejlécfájl határozza meg. A közös konvenció a fejlécfájl megnevezése az osztály neve után, például labda.,h tartalmazná az osztálygolyó felületét.
Egy felület nyilatkozat formában:
a fenti, plusz jel jelölésére osztály módszer vagy módszerek, hogy lehet nevezni az osztály is (nem egy esetben), valamint a mínusz jel jelöli például a módszerek, amelyek csak úgy hívnak, hogy egy konkrét esetben az osztály. Az osztálymódszerek szintén nem férnek hozzá a példányváltozókhoz.,
a fenti kód nagyjából megegyezik a következő c++ interfésszel:
vegye figyelembe, hogy az instancemethod2with2paraméterek: param2_callName: bemutatja a választó szegmensek argumentum-kifejezésekkel való összefonódását, amelyekhez a c/c++ – ban nincs közvetlen egyenérték.
visszatérési típusok lehetnek bármilyen szabványos C típus, mutató egy általános Objective-C objektumra, mutató egy adott típusú objektumra, például NSArray*, NSImage * vagy NSString*, vagy mutató arra az osztályra, amelyhez a módszer tartozik (instancetype). Az alapértelmezett visszatérési típus az Általános Objective-C típusú azonosító.,
metódus argumentumok kezdődik egy nevet címkézés az érv, amely része a metódus neve, majd egy kettőspont, majd a várt argumentum típusát zárójelben, valamint az argumentum neve. A címke elhagyható.
Az interfész definíciójának származéka a kategória, amely lehetővé teszi a módszerek hozzáadását a meglévő osztályokhoz.
ImplementationEdit
Az interfész csak az osztály interfészét deklarálja, nem pedig magukat a módszereket: a tényleges kódot az implementációs fájl tartalmazza., Implementation (method) fájlok általában a fájl kiterjesztés .m
, amely eredetileg azt jelentette, “üzenetek”.
@implementation classname+ (return_type)classMethod { // implementation}- (return_type)instanceMethod { // implementation}@end
a módszerek interfésznyilatkozataik segítségével íródnak.Az Objective-C és C összehasonlítása:
- (int)method:(int)i { return ;}
int function(int i) { return square_root(i);}
a szintaxis lehetővé teszi az argumentumok álnevesítését.
a módszer belső reprezentációi az Objective-C különböző implementációi között változnak., Ha a myColor az osztály színe, például módszer-changeColorToRed: zöld: kék: lehet, hogy belsőleg jelölt _i_Color_changeColorToRed_green_blue. Az i egy példány metódusra utal, az osztály, majd a metódusnevek csatolva vannak, a colonok pedig aláhúzásra változtak. Mivel a paraméterek sorrendje a módszernév része, nem változtatható meg kódolási stílusra vagy kifejezésre, mint a valódi megnevezett paramétereknél.
a funkció Belső nevét azonban ritkán használják közvetlenül. Általában az üzeneteket az Objective-C futásidejű könyvtárban meghatározott funkcióhívásokká alakítják át., Nem feltétlenül ismert a kapcsolat idején, hogy melyik módszert hívják, mert a vevő osztályát (az üzenetet elküldő objektumot) nem kell ismerni a futásidejéig.
InstantiationEdit
miután egy Objective-C osztály van írva, akkor példányosítható. Ezt úgy végezzük, hogy először az osztály (objektum) nem kezdeményezett példányát osztjuk ki, majd inicializáljuk. Egy objektum nem teljesen működőképes, amíg mindkét lépés befejeződött., Ezeket a lépéseket egy kódsorral kell végrehajtani, hogy soha ne legyen hozzárendelt objektum, amely nem ment át inicializáláson (és mivel nem bölcs dolog megtartani a közbenső eredményt, mivel a -init
más objektumot adhat vissza, mint amelyre hívják).,
Instantiation az alapértelmezett, no-paraméter inicializáló:
MyObject *foo = init];
instantiation egy egyéni inicializáló:
MyObject *foo = initWithString:myString];
abban az esetben, ha nincs egyéni inicializálás kerül végrehajtásra, az “új” módszer gyakran lehet használt helyett a Alloc-init üzenetek:
MyObject *foo = ;
is, egyes osztályok végre osztály módszer inicializátorok., Mint a +new
egyesülnek +alloc
vagy -init
, de ellentétben +new
, visszatérnek egy autoreleased például. Néhány osztály módszer initializers venni paraméterek:
MyObject *foo = ;MyObject *bar = ;
A alloc üzenetet oszt elég memória tartani minden esetben változó egy objektum, meghatározza minden esetben változók értéke nulla, majd bekapcsolja a memória be az osztály példánya; egyáltalán nem az inicializálás során a memória egy példányát a superclass.,
az init üzenet végrehajtja a példány létrehozását. Az init módszert gyakran a következőképpen írják:
- (id)init { self = ; if (self) { // perform initialization of object here } return self;}
a fenti példában vegye figyelembe a id
visszatérési típust. Ez a típus a “pointer to any Objective-C” kifejezést jelenti az Objective-C-ben (lásd a dinamikus gépelés részt).
az inicializáló mintát arra használjuk, hogy biztosítsuk, hogy az objektumot a szuperosztály megfelelően inicializálja, mielőtt az init módszer végrehajtja az inicializálást., A következő műveleteket hajtja végre:
- self = init üzenetet küld a superclass példánynak, majd az eredményt önmagához rendeli (mutató az aktuális objektumhoz).
- ha (self) ellenőrzi, hogy a visszaküldött objektummutató érvényes-e az inicializálás végrehajtása előtt.
- return selfReturns értéke önálló a hívó.
egy nem érvényes objektummutatónak nil értéke van; olyan feltételes kijelentések, mint például a ” ha ” nullmutatóként kezeli a nil-t, így az inicializálási kód nem kerül végrehajtásra, ha nulla értéket ad vissza., Ha van egy hiba az inicializálás az init módszert kell végezze el a szükséges tisztítás, beleértve küld egy “kiadás” üzenet, hogy egyéni, illetve vissza nulla jelzi, hogy az inicializálás nem sikerült. Az ilyen hibák ellenőrzését csak a superclass inicializálás után szabad elvégezni annak biztosítása érdekében, hogy az objektum megsemmisítése helyesen történjen.
Ha egy osztálynak egynél több inicializációs módszere van, akkor csak az egyiknek (a “kijelölt inicializátornak”) kell követnie ezt a mintát; másoknak a superclass inicializer helyett a kijelölt inicializátort kell hívniuk.,
ProtocolsEdit
más programozási nyelvekben ezeket “interfészeknek”nevezik.
Objective-C kiterjesztették mellett bevezetni a koncepció többszörös öröklés specifikáció, de nem végrehajtás, bevezetése révén protokollok. Ez egy elvont, többszörös öröklött bázisosztályként elérhető minta C++ – ban, vagy “interfészként” (mint a Java-ban és C# – ban). Az Objective-C az informális protokolloknak nevezett ad hoc protokollokat és a formális protokolloknak nevezett fordító-kényszerített protokollokat használja.,
az informális protokoll azon módszerek listája,amelyeket egy osztály választhat. Ezt a dokumentáció határozza meg, mivel nincs jelen a nyelven. Az informális protokollok kategóriaként kerülnek végrehajtásra (lásd alább) az NSObject-en, gyakran tartalmaznak opcionális módszereket, amelyek megvalósításuk esetén megváltoztathatják az osztály viselkedését. Például egy szövegmező osztálynak lehet egy delegáltja, amely informális protokollt valósít meg egy opcionális módszerrel a felhasználó által begépelt szöveg automatikus kitöltéséhez., A szövegmező felfedezi, hogy a küldött végrehajtja-e ezt a módszert (reflexió útján), és ha igen, felhívja a küldött módszerét az automatikus teljes funkció támogatására.
egy formális protokoll hasonló a Java, C# és Ada 2005 interfészéhez. Ez azoknak a módszereknek a listája, amelyeket bármely osztály végrehajthat. Változatai objective-C, mielőtt 2.0 szükséges, hogy egy osztály végre kell hajtania minden módszer egy jegyzőkönyv kijelenti magát, mint elfogadásáról; a fordító bocsát ki hiba, ha az osztály nem hajtja végre minden módszer a bejelentett protokollok. Célkitűzés-C 2.,0 hozzáadott támogatása jelölés bizonyos módszerek egy protokoll opcionális, a fordító nem érvényesíteni végrehajtása opcionális módszerek.
a protokoll végrehajtásához egy osztályt kell bejelenteni, amelyről azt kell mondani, hogy megfelel. Ez kimutatható futási időben. A formális protokollok semmilyen implementációt nem tudnak biztosítani; egyszerűen biztosítják a hívóknak, hogy a protokollnak megfelelő osztályok megvalósítást biztosítanak. A következő / Apple könyvtárban az elosztott objektumok rendszer gyakran használ protokollokat egy távoli rendszeren végrehajtó objektum képességeinek ábrázolására.,
a szintaxis
@protocol NSLocking- (void)lock;- (void)unlock;@end
azt jelzi, hogy van a zárolás absztrakt ötlete. Az osztálydefinícióban feltüntetve, hogy a protokoll végrehajtásra kerül,
@interface NSLock : NSObject <NSLocking>// ...@end
az NSLock példányai azt állítják, hogy végrehajtást nyújtanak a két példány módszerére.
Dynamic typingEdit
Objective-C, mint Smalltalk, használhatja dinamikus gépelés: egy objektum lehet küldeni egy üzenetet, hogy nincs megadva a felületen., Ez lehetővé teszi a nagyobb rugalmasságot, mivel lehetővé teszi egy objektum számára, hogy” elfogjon ” egy üzenetet, és elküldje az üzenetet egy másik objektumnak, amely megfelelően reagálhat az üzenetre, vagy hasonlóképpen elküldi az üzenetet egy másik objektumnak. Ezt a viselkedést üzenet továbbításnak vagy delegációnak nevezik (lásd alább). Alternatív megoldásként egy hibakezelő is használható abban az esetben, ha az üzenet nem továbbítható. Ha egy objektum nem továbbít egy üzenetet, válaszol rá, vagy hibát kezel, akkor a rendszer futásidejű kivételt generál., Ha az üzeneteket nil-re (A null objektummutatóra) küldi, akkor a fordító beállításaitól függően csendben figyelmen kívül hagyja vagy általános kivételt emel.
statikus gépelési információk opcionálisan hozzáadhatók a változókhoz is. Ezt az információt ezután a fordítási időben ellenőrzik. A következő négy nyilatkozatban egyre konkrétabb típusú információkat szolgáltatnak. A kijelentések futási időben egyenértékűek, de az extra információ lehetővé teszi a fordító számára, hogy figyelmeztesse a programozót, ha az átadott argumentum nem felel meg a megadott típusnak.,
- (void)setMyValue:(id)foo;
a fenti nyilatkozatban a foo bármely osztályba tartozhat.
- (void)setMyValue:(id<NSCopying>)foo;
a fenti nyilatkozatban a foo bármely olyan osztály példánya lehet, amely megfelel a NSCopying
protokollnak.
- (void)setMyValue:(NSNumber *)foo;
a fenti nyilatkozatban a foo-nak az NSNumber osztály példányának kell lennie.
- (void)setMyValue:(NSNumber<NSCopying> *)foo;
a fenti nyilatkozatban a foo-nak az NSNumber osztály példányának kell lennie, és meg kell felelnie a NSCopying
protokollnak.,
az Objective-C-ben minden objektum mutatóként jelenik meg, a statikus inicializálás pedig nem engedélyezett. A legegyszerűbb objektum az a típus, amelyre az ID (objc_obj *) mutat, amely csak egy isa mutatóval rendelkezik, amely leírja az osztályát. A C-ből más típusok, mint az értékek és a structs, változatlanok, mert nem részei az objektumrendszernek. Ez a döntés különbözik a C++ objektummodelltől, ahol a structs és az osztályok egyesülnek.
ForwardingEdit
Objective-C lehetővé teszi egy üzenet küldését egy olyan objektumra, amely nem válaszol., Ahelyett, hogy válaszolna vagy egyszerűen eldobná az üzenetet, az objektum továbbíthatja az üzenetet egy olyan objektumhoz, amely válaszolhat. A továbbítás bizonyos tervezési minták, például a megfigyelő minta vagy a proxy minta végrehajtásának egyszerűsítésére használható.
Az objective-C runtime meghatározza, hogy egy pár módszerek Objektum
Egy tárgyat kíván végrehajtani továbbítása kell csak, hogy felülírja az új módszer egy új módja annak, hogy meghatározza a továbbítási viselkedés. Az Action method performv:: nem szükséges felülírni, mivel ez a módszer csupán a választó és az argumentumok alapján hajt végre egy műveletet., Figyeljük meg aSEL
típust, amely az Objective-C típusú üzenetek típusa.
Megjegyzés: OpenStep, Cocoa és GNUstep, az Objective-C általánosan használt keretrendszerei, az egyik nem használja az objektumosztályt. A – (void)forwardInvocation: (NSInvocation *)anInvocation módszer az NSObject osztály használják, hogy nem továbbítás.
ExampleEdit
itt egy példa egy olyan programra, amely bemutatja a továbbítás alapjait.
szállítmányozó.h szállítmányozó.m recipiens.h
#import <objc/Object.h>// A simple Recipient object.@interface Recipient : Object- (id)hello;@end
címzett.m
#import "Recipient.h"@implementation Recipient- (id)hello { printf("Recipient says hello!\n"); return self;}@end
fő.,m
NotesEdit
ha GCC-vel állítják össze, a fordító jelentése:
a fordító a korábban készített pontot jelenti, hogy a szállítmányozó nem válaszol a hello üzenetekre. Ebben a körülmények között biztonságos figyelmen kívül hagyni a figyelmeztetést, mivel a továbbítást végrehajtották. A program futtatása ezt a kimenetet hozza létre:
$ ./a.outRecipient says hello!
CategoriesEdit
az Objective-C tervezése során az egyik fő probléma a nagy kódbázisok karbantarthatósága volt., A strukturált programozási világ tapasztalatai azt mutatták, hogy a kód javításának egyik fő módja az volt, hogy kisebb darabokra bontsa. Az Objective-C a Smalltalk implementációkból kölcsönözte és bővítette a kategóriák fogalmát, hogy ezzel segítse a folyamatot.
továbbá a kategórián belüli módszerek futási időben kerülnek hozzáadásra egy osztályhoz. Így kategóriák lehetővé teszi a programozó, hogy hozzá módszerek, hogy egy meglévő osztály – nyílt osztály -, nem kell újrafordítani, hogy osztály vagy még hozzáférhet a forráskódhoz., Például, ha egy rendszer nem tartalmaz helyesírás-ellenőrzőt a karakterlánc végrehajtásában, hozzáadható a karakterlánc forráskódjának módosítása nélkül.
a kategóriákon belüli módszerek megkülönböztethetetlenek az osztály módszereitől a program futtatásakor. Egy Kategória teljes hozzáférést biztosít az osztály összes példányváltozójához, beleértve a privát változókat is.
Ha egy kategória ugyanazt a módszert írja alá, mint egy osztály meglévő módszere, akkor a kategória módszere kerül elfogadásra. Így a kategóriák nem csak módszereket adhatnak hozzá egy osztályhoz, hanem helyettesíthetik a meglévő módszereket is., Ez a funkció használható a hibák kijavítására más osztályokban a módszerek átírásával, vagy globális változást okozhat egy osztály viselkedésében egy programon belül. Ha két kategóriának van azonos nevű, de eltérő metódusaláírással rendelkező módszere, akkor nem határozható meg, hogy melyik kategória metódusát fogadják el.
más nyelvek megpróbálták ezt a funkciót többféle módon hozzáadni. TOM egy lépéssel tovább vitte az Objective-C rendszert, és lehetővé tette a változók hozzáadását is. Más nyelvek inkább prototípus alapú megoldásokat használtak, a legjelentősebb az önálló.
A C# és a Visual Basic.,A NET nyelvek felületesen hasonló funkciókat valósítanak meg kiterjesztési módszerek formájában, de ezek nem férnek hozzá az osztály privát változóihoz. A Ruby és több más dinamikus programozási nyelv a technikát “majom foltozásnak”nevezi.
A Logtalk olyan kategóriák (első osztályú entitások) fogalmát valósítja meg, amelyek az objektív-C kategóriák funkcionalitását tartalmazzák (a Logtalk kategóriák finom szemcsés összetételű egységekként is használhatók pl. új osztályok vagy prototípusok meghatározásakor; különösen a Logtalk kategóriát gyakorlatilag tetszőleges számú osztály és prototípus importálhatja).,
Példa használata categoriesEdit
Ez a példa épít fel egy Egész osztály meghatározásával első alapvető osztályba, csak accessor módszerekkel végrehajtani, majd hozzátéve a két kategória, Számtani, illetve Megjeleníteni, amely kiterjed az alap osztály. Míg a kategóriák hozzáférhetnek az alaposztály magánadattagjaihoz, gyakran jó gyakorlat, hogy ezeket a magánadattagokat accessor módszerekkel érik el, ami segít a kategóriákat függetlenebbé tenni az alaposztálytól. Az ilyen accessors végrehajtása a kategóriák egyik tipikus használata. A másik az, hogy kategóriákat használjon módszerek hozzáadásához az alaposztályhoz., Nem tekinthető azonban jó gyakorlatnak az alosztályok kategóriáinak használata, más néven monkey patching. Az informális protokollok kategóriaként kerülnek végrehajtásra az NSObject alaposztályon. Konvenció szerint az alaposztályokat kiterjesztő kategóriákat tartalmazó fájlok a BaseClass+ExtensionClass nevet fogják használni.h.
egész szám.h
#import <objc/Object.h>@interface Integer : Object { int integer;}- (int)integer;- (id)integer:(int)_integer;@end
Integer.M egész+számtani.h
#import "Integer.h"@interface Integer (Arithmetic)- (id) add: (Integer *) addend;- (id) sub: (Integer *) subtrahend;@end
Integer+aritmetika.M egész+kijelző.h
#import "Integer.h"@interface Integer (Display)- (id) showstars;- (id) showint;@end
Integer+Display.m main.,az M
NotesEdit
összeállítást például a következők végzik:
gcc -x objective-c main.m Integer.m Integer+Arithmetic.m Integer+Display.m -lobjc
lehet kísérletezni a #import ” Integer+aritmetika elhagyásával.h ” és vonalak és kihagyva egész+számtani.m összeállításban. A program továbbra is fut. Ez azt jelenti, hogy szükség esetén össze lehet keverni a hozzáadott kategóriákat; ha egy kategóriának nem kell valamilyen képességgel rendelkeznie, egyszerűen nem lehet összeállítani.
PosingEdit
Objective-C lehetővé teszi egy osztály számára, hogy teljesen helyettesítsen egy másik osztályt egy programon belül. A helyettesítő osztály azt mondják, hogy” jelentenek, mint ” a cél osztály.,
A posing osztályt a Mac OS X v10.5 verziójával elavultnak nyilvánították, és a 64 bites futásidőben nem érhető el. Hasonló funkcionalitás érhető el a módszer swizzling kategóriákban, hogy swap egy módszer végrehajtását egy másik, hogy ugyanaz az aláírás.
a pózolást továbbra is támogató verziók esetében a célosztályba küldött összes üzenetet ehelyett a pózoló osztály fogadja. Számos korlátozás létezik:
- egy osztály csak közvetlen vagy közvetett szuperosztályaként jelentkezhet.,
- a pózoló osztály nem határozhat meg olyan új példányváltozókat, amelyek hiányoznak a célosztályból (bár meghatározhatja vagy felülírhatja a módszereket).
- előfordulhat, hogy a célosztály nem kapott üzenetet a pózolás előtt.
a pózolás, hasonlóan a kategóriákhoz, lehetővé teszi a meglévő osztályok globális fokozását. Pózol lehetővé teszi a két funkció hiányzik kategóriák:
- egy pózol osztály hívhatja felülbírált módszerek révén super, így magában foglalja a végrehajtását a célosztály.
- egy pózoló osztály felülírhatja a kategóriákban meghatározott módszereket.,
például
Ez elfogja a setMainMenu NSApplication-re történő minden meghívását.
# importEdit
A C nyelvben a#include
A fordítás előtti irányelv mindig azt eredményezi, hogy a fájl tartalmát beillesztik a forrásba. Objective-C rendelkezik a #import
irányelvvel, azzal egyenértékű, hogy minden fájl csak egyszer szerepel összeállítási egységenként, kiküszöbölve az őrök szükségességét.