Célkitűzés-C
| Célkitűzés-C | ||
|---|---|---|
| ? | ||
| Általános információ | ||
| Gyakori bővítmények | h, m, mm és C | |
| Paradigma | objektum orientált | |
| Megjelent | 1980 | |
| Tervezte | Brad Cox | |
| típusú rendszer | erős, statikus | |
| megvalósítások | számos | |
| befolyásolta | C , Smalltalk | |
| befolyásolta | Objective-C++ , Java | |
Az Objective-C egy objektumorientált programozási nyelv , amelyet a C szuperkészleteként hoztak létre, hogy megvalósítsa a Smalltalk -szerű objektummodellt . Eredetileg Brad Cox és a StepStone Corporation hozta létre 1980 -ban . 1988 - ban NEXTSTEP programozási nyelvként fogadták el, majd 1992 - ben adták ki a GPL licenc alatt a GCC fordítóhoz . Jelenleg a Mac OS X , iOS és GNUstep fő programozási nyelveként használják , amellett, hogy Swift .
Előzmények
Az 1980-as évek elején a szoftvereket strukturált programozással fejlesztették ki. A strukturált programozást azért hozták létre, hogy segítsenek a programok kis részekre bontásában, megkönnyítve a fejlesztést, amikor az alkalmazás nagyon nagy lett. Mivel azonban a problémák idővel tovább nőttek, a strukturált programozás bonyolulttá vált, mivel egyes programozók elrontották az utasítások ismétlődő meghívását, ami spagetti kódhoz vezetett, és megnehezítette a kód újrafelhasználását.
Sokan látták, hogy az objektum-orientált programozás lenne a megoldás a problémára. Valójában a Smalltalk már sok ilyen problémát megoldott: a világ legbonyolultabb rendszerei közül néhányat a Smalltalk táplált. A Smalltalk azonban egy virtuális gépet használt, amely sok memóriát igényelt, és túl lassú volt.
Az Objective-C-t elsősorban Brad Cox és Tom Love hozta létre az 1980-as évek elején a Stepstone cégüknél. Mindkettőjüket 1981-ben az ITT Programozási Technológiai Központjában mutatták be a Smalltalknak. Cox érdeklődni kezdett a szoftverfejlesztés újrafelhasználási problémái iránt. Felismerte, hogy egy olyan nyelv, mint a Smalltalk, elengedhetetlen lenne az ITI Corporation fejlesztői számára hatékony fejlesztői környezetek felépítéséhez. Cox elkezdte módosítani a C fordítót, hogy hozzáadja a Smalltalk bizonyos képességeit. Hamarosan kiterjesztette az objektum-orientált programozást a C-re, amit "OOPC-nek" ( Objektumorientált programozás C- ben ) nevezett el. Eközben Love-t 1982-ben a Shlumberger Research bérelte fel, és lehetősége volt megszerezni a Smalltalk-80 első példányát, ami befolyásolta programozói stílusát.
Annak bizonyítására, hogy valódi előrelépés történt, Cox megmutatta, hogy ahhoz, hogy a szoftverösszetevők valóban felcserélhetőek legyenek, csak kisebb változtatásokat igényel a meglévő eszközökön. Konkrétan az objektumokat rugalmas módon kellett támogatniuk, használható könyvtárkészlettel kellett rendelkezniük, és lehetővé kell tenni a kód (és a kódhoz szükséges erőforrások) többplatformos formátumba történő csomagolását.
Cox és Love ezután új céget alapított, a Productivity Products Internationalt (PPI), hogy piacra dobja termékét, amely egy Objective-C fordító volt egy sor hatékony könyvtárral.
1986-ban Cox közzétette az Objective-C fő leírását eredeti formájában az Object-Oriented Programming, An Evolutionary Approach című könyvben . Bár gondosan rámutatott arra, hogy sok olyan újrafelhasználási probléma van, amelyek nem nyelvfüggőek, az Objective-C-t gyakran részletesen összehasonlították más nyelvekkel.
Népszerűsítés a NeXT segítségével
1988-ban a NeXT licencelte az Objective-C-t a StepStone-tól (a PPI új neve, az Objective-C márkatulajdonos), és kiterjesztette a GCC fordítót az Objective-C támogatására, miközben kifejlesztette az AppKit és Foundation könyvtárakat is. Kit, amelyen a NeXTstep alapultak . Míg a NeXT munkaállomások nem tudtak nagy hatást elérni a piacon, az eszközöket széles körben dicsérték az iparágban. Ez arra késztette a NeXT-t, hogy felhagyott a hardvergyártással, és a szoftvereszközökre összpontosított, és eladta a NeXTstep-et (és az OpenStep-et) az egyéni programozás platformjaként.
A GCC kiterjesztésére irányuló munkát Steve Naroff vezette, aki a StepStone-tól csatlakozott a NeXT-hez. A fordítóprogram módosításait a GPL licencfeltételei szerint tették elérhetővé , de a futásidejű könyvtárak nem, így a nyílt forráskódú hozzájárulás használhatatlanná vált a nagyközönség számára. Ez arra késztetett más vállalatokat, hogy nyílt forráskódú licencek alatt fejlesszék ezeket a könyvtárakat. Később Steve Naroff is nagyban hozzájárult az Apple-nek az Objective-C Clang felület kiépítéséhez .
A GNU Project megkezdte a munkát a Cocoa ingyenes szoftveres megvalósításán, a GNUstep néven és az OpenStep szabványon alapul. [ 1 ] Dennis Glatting írta az első GNU Objective-C futási rendszert 1992-ben. Az 1993 óta használt GNU Objective-C futásidejű rendszer egyike azoknak, amelyeket Kresten Krab Thorup fejlesztett ki, amikor egyetemista volt Dániában . . Thorup a NeXT-nél is dolgozott 1993 és 1997 között.
Apple és Swift fejlesztés
A NeXT 1996-os felvásárlása után az Apple az OpenStepet használta új operációs rendszerében, a Mac OS X -ben. Ebbe beletartozott az Objective-C és a NeXT Objective-C alapú fejlesztőeszköze, a Project Builder (később kibővítve, ma Xcode néven ismert ), valamint az interfésztervező eszköz, az Interface Builder. Az Apple jelenlegi Cocoa API -jának nagy része OneStep interfészobjektumokon alapul, és ez a legszélesebb körben használt Objective-C fejlesztői környezet az aktív fejlesztéshez.
A 2014-es WWDC alkalmával az Apple bejelentette, hogy a Cocoa fejlesztésben az Objective-C-t lecseréli az új Swift nyelvre , amelynek neve "Objective-C a C nélkül".
Szintaxis
Az Objective-C egy nagyon vékony rétegből áll a C tetején, és egyben a C szigorú szuperhalmaza is . Vagyis bármilyen C nyelven írt programot le lehet fordítani egy Objective-C fordítóval, és szabadon beilleszthetünk C kódot is egy Objective-C osztályba.
Vagyis a klasszikus „Hello World” program konzolon való futtatásához a következő kód használható:
#import <stdio.h>
int main ( int argc , const char * argv [] ) {
printf ( "Hello World \n " );
return 0 ;
}
A fenti kód különbözik a szokásos C kódtól az első #import utasításban, amely eltér a klasszikus C #include-tól, de a printf("") függvény tiszta C. Az Objective-C saját függvénye egy karakterlánc kinyomtatására a konzolban jelentése NSLog(@""); ennek használatával az előző kód a következő lenne:
int main ( int argc , const char * argv [ ] ) {
NSLog ( @"Hello World \n " );
return 0 ;
}
Az Objective-C objektum szintaxisa a Smalltalk -ból származik . A nem objektum-orientált műveletek szintaxisa (beleértve a primitív változókat, az előfeldolgozást, a kifejezéseket, a függvénydeklarációkat és a függvényhívásokat) megegyezik a C-vel, míg az objektumorientált szolgáltatások szintaxisa hasonló a Smalltalk üzenetkezeléshez.
Üzenetek
Az Objective-C objektumorientált programozási modellje az objektumpéldányoknak való üzenetek küldésén alapul. Ez eltér a C++ által használt Simula - stílusú programozási modelltől , és ez a megkülönböztetés szemantikailag fontos. Az Objective-C-ben nem lehet metódusokat hívni ; az egyik üzenetet küld , és a két fogalom közötti különbség abban rejlik, hogy az üzenet vagy metódusnév által hivatkozott kód hogyan kerül végrehajtásra. A Simula-stílusú nyelvekben a metódus nevét a legtöbb esetben a fordító egy kódszakaszhoz köti a célosztályban, de a Smalltalk és az Objective-C esetén az üzenet továbbra is csak egy név, és futás közben kerül feloldásra: a fogadó objektum feladata magának az üzenetnek az értelmezése. Ennek egyik következménye, hogy az általa átadott rendszerüzenet nem típusellenőrzött: az üzenet címzett objektum (az úgynevezett fogadó ) nem garantáltan válaszol egy üzenetre, és ha nem, akkor egyszerűen figyelmen kívül hagyja.és null mutatót ad vissza.
A metódusüzenetnek az obj mutató által mutatott objektumnak való elküldéséhez a következő C++ kódra van szükség:
obj -> metódus ( paraméter );
míg az Objective-C-ben a következőképpen íródik:
[ obj metódus : paraméter ];
Mindkét programozási stílusnak megvannak a maga erősségei és gyengeségei. A szimulációs stílusú OOP lehetővé teszi a többszörös öröklődést és a gyors végrehajtást a fordítási idejű összerendelés használatával, amikor csak lehetséges, de alapértelmezés szerint nem támogatja a dinamikus összerendelést. Ez arra kényszeríti az összes metódust, hogy megfelelő implementációval rendelkezzen, kivéve, ha virtuálisak (a hívás indításához továbbra is metódus-megvalósítás szükséges). A Smalltalk-stílusú OOP lehetővé teszi, hogy az üzenetek implementációmentesek legyenek – például objektumok egész gyűjteménye küldhet üzenetet anélkül, hogy félne a futásidejű hibáktól. Az üzenetek küldéséhez nincs szükség objektum meghatározására fordításkor. (Lásd a dinamikus gépelés részt alább ) a dinamikus kötés további előnyeiért.
Meg kell azonban jegyezni, hogy az üzenetek értelmezésének többletköltsége miatt az Objective-C-ben lévő üzenet legfeljebb háromszor annyi ideig tart, mint egy virtuális metódus hívása C++-ban. [ 2 ]
Interfészek és megvalósítások
Az Objective-C megköveteli, hogy egy osztály interfésze és megvalósítása külön kódblokkban legyen. Megállapodás szerint az interfész egy fejlécfájlba, a megvalósítás pedig egy kódfájlba kerül; Az általában .h utótagú fejlécfájlok hasonlóak a C fejlécfájlokhoz; implementációs (metódus) fájlok, amelyek jellemzően .m utótaggal rendelkeznek, nagyon hasonlóak lehetnek a C kódfájlokhoz.
Interfész
Az osztály interfészt általában a fejlécfájlban határozzák meg. Gyakori konvenció, hogy a fejlécfájlt ugyanazzal a névvel nevezik el, mint az osztályt. A Class osztály interfésze tehát a Class.h fájlban található .
Az űrlap interfész deklarációja:
@interface classname : szuperosztálynév
{
// példányváltozók
}
+ osztályMódszer1 ;
+( return_type ) class Method2 ;
+( return_type ) class Method3 : ( param1_type ) parameter_varName ;
-( visszatérési_típus ) példányMódszer1 : ( param1_type ) param1_varName : ( param2_type ) param2_varName ;
-( visszatérési_típus ) példányMódszer2Paraméterrel : ( param1_type ) param1_varName andOtherParameter : ( param2_type ) param2_varName ;
@vége
A pluszjelek osztálymetódusokat , a mínuszjelek a példánymetódusokat jelölik. Az osztálymetódusok nem férnek hozzá a példányváltozókhoz.
Ha C++-ból érkezik, a fenti kód valami ilyesmivel egyenértékű:
osztály osztálynév : szuperosztálynév {
nyilvános :
// példányváltozók
// Osztály (statikus) függvények static void * classMethod1 ();
static return_type classMethod2 ( );
static return_type classMethod3 ( param1_type parameter_varName ) ;
// Példány (tag) függvények
return_type instanceMethod1 ( param1_type param1_varName , param2_type param2_varName );
return_type instanceMethod2WithParameter ( param1_type param1_varName , param2_type param2_varName = alapértelmezett );
};
Ne feledje, hogy instanceMethod2WithParameterbemutatja az Objective-C paraméter-elnevezési képességét, amelynek nincs közvetlen megfelelője a C/C++-ban.
A visszatérési típusok bármilyen szabványos C típusúak lehetnek, egy általános Objective-C objektumra mutató mutató, vagy egy adott típusra mutató mutató, például NArray *, NSImage * vagy NSString *. Az alapértelmezett visszatérési típus az idObjective-C általános típus.
A metódus argumentumai kettősponttal kezdődnek, amelyet zárójelben a várt argumentumtípus követ, majd az argumentum neve. Bizonyos esetekben (pl. rendszer API-k írásakor) hasznos minden paraméter elé egy leíró szöveget hozzáadni.
-( void ) setRangeStart: ( int ) start End: ( int ) end ;
-( void ) importDocumentWithName: ( NSString * ) name withSpecifiedPreferences: ( Preferences * ) prefs beforePage : ( int ) insertPage ;
Megvalósítás
Az interfész csak az osztály interfészét deklarálja, magukat a metódusokat nem; a tényleges kód az implementációba van írva. Az implementációs fájlok (metódusok) általában .m kiterjesztéssel rendelkeznek .
@ megvalósítási osztálynév
+ classMethod {
// megvalósítás
}
- instance Method {
// megvalósítás
}
@vége
A metódusok az interfész deklarációikkal együtt vannak megírva. Az Objective-C és a C összehasonlítása:
-( int ) metódus: ( int ) i {
return [ saját négyzetgyök : i ];
}
int függvény ( int i ) {
return négyzetgyök ( i );
}
A szintaxis támogatja az argumentumok pszeudo-elnevezését.
-( int ) changeColorToRed: ( float ) red green: ( float ) green blue: ( float ) blue
[ myColor changeColorToRed : 5.0 green : 2.0 blue : 6.0 ];
Ennek a módszernek a belső reprezentációja a különböző Objective-C implementációk között változik. Ha a myColor a Color osztályba tartozik , akkor a -changeColorToRed:green:blue: metóduspéldány _i_Color_changeColorToRed_green_blue címkével jelölhető meg . Az i metóduspéldányra utal, az osztály- és metódusnevekkel együtt, a kettőspontot pedig aláhúzásjelek helyettesítik. Mivel a paraméterek sorrendje a metódus nevének része, nem módosítható a kódolási stílusnak megfelelően.
A belső függvényneveket azonban ritkán használják közvetlenül, és az üzeneteket általában az Objective-C futásidejű könyvtárban meghatározott függvényhívásokká alakítják át – a meghívandó metódus nem feltétlenül ismert a bind-time-ben: a fogadó osztály (az objektum, amelyik küldte a üzenet) futásidőig nem kell tudnia róla.
Példányosítás
Ha egy osztályt az Objective-C-ben írtunk, akkor példányosítható. Ez úgy történik, hogy először memóriát foglal le az új objektum számára, majd inicializálja azt. Egy objektum nem működik teljesen mindaddig, amíg mindkét lépés be nem fejeződik. Ezeket a lépéseket általában egyetlen kódsorral hajtják végre:
MyObject * o = [[ MyObject alloc ] init ] ;
Az alloc hívás elegendő memóriát foglal le az objektum összes példányváltozójának tárolására, és az init hívás felülbírálható, hogy a példányváltozókat meghatározott értékekre állítsa a létrehozáskor. Az init metódust gyakran a következőképpen írják:
-( id ) init {
self = [ szuper init ];
if ( self ) {
ivar1 = ''' érték1 ''' ;
ivar2 = érték2 ;
.
.
.
}
visszatérő én ;
}
Protokollok
Az Objective-C kiterjesztésre került a NeXT -ben, hogy bevezesse a többszörös öröklődés fogalmát a specifikációból, de nem a megvalósítást, a protokollok bevezetésével . Ez egy életképes modell, akár többszörösen örökölt absztrakt alaposztályként a C++-ban, akár "interfészként" (mint a Java vagy a C# ). Az Objective-C ad-hoc protokollokat használ, amelyeket informális protokolloknak neveznek , és a fordítónak be kell tartania az úgynevezett formális protokollokat .
Dinamikus gépelés
Az Objective-C, akárcsak a Smalltalk, használhat dinamikus gépelést : egy objektum olyan üzenetet kaphat, amely nincs megadva a felületén. Ez lehetővé teszi a rugalmasság növelését, mivel lehetővé teszi egy objektum számára, hogy "elkapjon" egy üzenetet, és elküldje azt egy másik objektumnak, amely megfelelően reagál az üzenetre, vagy hasonló módon továbbítja az üzenetet egy másik objektumnak. Ezt a viselkedést üzenettovábbításnak vagy delegálásnak nevezik (lásd alább). Alternatív megoldásként hibakezelő is használható arra az esetre, ha az üzenetet nem lehet továbbítani. Ha egy objektum nem továbbít üzenetet, nem válaszol rá, vagy nem kezel hibát, akkor a rendszer futás közben kivételt dob. Ha az üzeneteket a nullára (a null objektum mutatójára) küldjük, akkor azokat csendben figyelmen kívül hagyja, vagy általános kivételt jelent a fordító beállításaitól függően.
A statikusan beírt információk opcionálisan hozzáadhatók a változókhoz. Ezt az információt a fordításkor ellenőrzik. A következő négy állítás egyre specifikusabb típusú információkat tartalmaz. Ezek a deklarációk futás közben egyenértékűek, de a kiegészítő információk lehetővé teszik a fordító számára, hogy figyelmeztesse a programozót, ha az átadott argumentum nem egyezik a megadott típussal.
- ( void ) setMyValue: ( id ) foo ;
A fenti deklarációban a foo bármely osztályba tartozhat.
- ( void ) setMyValue: ( id < NSCopying > ) foo ;
A fenti deklarációban a foo bármely olyan osztály példánya lehet, amely megfelel az NSCopying protokollnak .
- ( void ) setMyValue: ( NSNumber * ) foo ;
A fenti deklarációban a foo -nak az NSNumber osztály példányának kell lennie .
- ( void ) setMyValue: ( NSNumber < NSCopying > * ) foo ;
A fenti deklarációban a foo -nak az NSNumber osztály példányának kell lennie , és meg kell felelnie az NSCopying protokollnak .
Továbbítás
Az Objective-C lehetővé teszi üzenet küldését olyan objektumnak, amely esetleg nem válaszol. Ahelyett, hogy válaszolna vagy egyszerűen figyelmen kívül hagyná az üzenetet, egy objektum továbbíthatja az üzenetet egy másik objektumnak, amely válaszolni tud rá. A továbbítás felhasználható bizonyos tervezési minták , például megfigyelő vagy proxy megvalósításának egyszerűsítésére .
Az Objective-C futtatókörnyezete néhány metódust határoz meg a Objectkövetkezőben:
- továbbítási módok:
- ( retval_t ) forward: ( SEL ) sel args: ( arglist_t ) args ; // GCC-vel - ( id ) forward: ( SEL ) sel args: ( marg_list ) args ; // NeXT/Apple rendszerekkel
- cselekvési módszerek:
- ( retval_t ) performv: ( SEL ) sel args: ( arglist_t ) args ; // GCC-vel - ( id ) performV: ( SEL ) sel args ( marg_list ) args ; // NeXT/Apple rendszerekkel
A továbbítást megvalósítani kívánó objektumnak csak felül kell írnia a továbbítási metódust egy új metódussal, amely meghatározza a továbbítási viselkedést. A műveletmódszert performv::nem kell felülírni, mivel ez a metódus csupán egy műveletet hajt végre a választó és az argumentumok alapján. A típus SELaz Objective-C üzeneteinek típusa.
Megjegyzés: Az openStep, Cocoa és GNUstep, az általánosan használt Objective-C munkaterületeken nem kell használnia a Object. - (void)forwardInvocation:(NSInvocation *)anInvocationaz osztály metódust NSObjecthasználjuk a továbbítás végrehajtására.
Példa
Íme egy példa egy programra, amely bemutatja a továbbítás alapjait.
- Szállítmányozó.h
# import <objc/Object.h>
@interface Forwarder : Object {
azonosító címzett ; // Az objektum, amelyre az üzenetet továbbítani szeretnénk. }
// Hozzáférési módszerek
- ( id ) címzett ;
- ( id ) setRecipient: ( id ) _recipient ;
@vége
- Szállítmányozó.m
# import "Forwarder.h"
@implementation Forwarder
- ( retval_t ) forward: ( SEL ) sel args: ( arglist_t ) args {
/*
* Ellenőrizze, hogy a címzett válaszol-e az üzenetre.
* Ez lehet, de lehet, hogy nem kívánatos, például ha a fogadó
* nem válaszol az üzenetre, akkor maga újraküldheti azt.
*/
if ([ címzett válaszolToSelector : sel ]) {
return [ recipient performv : sel args : args ];
} másik {
return [ self error : "A vevő nem válaszol" ];
}
}
- ( id ) setRecipient: ( id ) _recipient {
[ címzett automatikus kiadása ];
konténer = [ _címzett megtartása ];
visszatérő én ;
}
- ( azonosító ) címzett {
visszaküldő címzett ;
}
@vége
- Címzett.h
# import <objc/Object.h>
// Egyszerű fogadó objektum. @interface Címzett : Objektum
- ( id ) helló ;
@vége
- Címzett.m
# import "Recipient.h"
@implementation Recipient
- ( id ) helló {
printf ( "A vevő köszön! \n " );
visszatérő én ;
}
@vége
- fő.m
# import "Forwarder.h"
# import "Címzett.h"
int main ( void ) {
Forwarder * forwarder = [ Forwarder new ];
Címzett * címzett = [ Címzett új ];
[ forwarder setRecipient : recipient ]; // Válassza ki a vevőt. /* * Ügyeljen arra, hogy a feladó ne válaszoljon az üdvözlésre! Ezt továbbítják. * Minden fel nem ismert metódust továbbítunk a vevőnek * (ha a címzett válaszol rájuk, ahogy a Továbbítóban is szerepel) */
[ szállítmányozó hello ];
[ címzett kiadás ];
[ továbbító kiadás ];
return 0 ;
}
Jegyzetek
A gcc -vel fordítva a fordító a következőket jelenti:
$ gcc -x object-c -Wno-import Forwarder.m Recipient.m main.m -lobjc
main.m: A `main' függvényben:
main.m:12: figyelmeztetés: A továbbító nem válaszol a 'hello'-ra
$
A fordító a korábban leírtak szerint arról számol be, hogy nem válaszol a helloForwarder üzenetekre . Ebben az esetben nyugodtan figyelmen kívül hagyhatja a figyelmeztetést, mivel a továbbítás megvalósult. A program futtatása a következő kimenetet adja:
& ./a.out
A kagyló köszön!
Nyelvi változatok
Objective-C++
Az Objective-C++ a GNU Compiler Collection interfész és a Clang által támogatott nyelvváltozat , amely képes C++ és Objective-C szintaxis kombinációját használó forráskódfájlokat fordítani. Az Objective-C++ hozzáadja a C++-hoz azokat a kiterjesztéseket, amelyeket az Objective-C a C-hez. Mivel semmi sem történik a különböző nyelvek jellemzői mögötti szemantika egységesítésére, bizonyos korlátozások léteznek:
- A C++ osztály nem származhat Objective-C osztályból és fordítva.
- A C++ névterek nem deklarálhatók Objective-C deklaráción belül.
- Az Objective-C deklarációknak globálisan kell megjelenniük, nem egy C++ deklaráción belül.
- Az Objective-C osztályokban nem lehetnek olyan C++ osztályok változó példányai, amelyek nem rendelkeznek alapértelmezett konstruktorral vagy egy vagy több virtuális metódussal rendelkeznek, de a C++ objektumokra mutató mutatók korlátozás nélkül használhatók változó példányként (az -init metódusban vannak hozzárendelve).
- A C++ "érték szerint" szemantikája nem alkalmazható Objective-C objektumokra, amelyek csak mutatókon keresztül érhetők el.
- Az Objective-C deklaráció nem lehet C++ deklarációs sablonon belül, és fordítva. Az Objective-C típusok (például az Osztálynév * ) azonban használhatók C++ sablonparaméterként.
- Az Objective-C és a C++ kivételkezelés eltérő; minden nyelv csak a saját kivételeit tudja kezelni. Ezt a legutóbbi verziók enyhítik, ha az Objective-C kivételeket teljesen lecserélik C++ kivételekre (ahogyan az Apple teszi), vagy részben az Objective-C++ könyvtár összekapcsolásával (GNUstep libobjc2).
- Legyen óvatos, mivel az Objective-C és a C++ futásidejű kivételdestruktor hívásai nem egyeznek (például a C++ destruktor nem hívódik meg, ha egy Objective-C kivétel kikerül egy C++ objektum hatóköréből). C++). Az újabb 64 bites verziók ezt az interoperabilitás bevezetésével oldják meg a C++ kivételekkel. [ 3 ]
- Az Objective-C blokkok és a C++11 lambdák különböző entitások, azonban a blokk transzparens módon generálódik a Mac OS X rendszeren, amikor egy lambda átadásra kerül, ahol blokkot várnak. [ 4 ]
Objective-C 2.0
A 2006-os Worldwide Developers Conference -en az Apple bejelentette az Objective-C 2.0 kiadását, amely az Objective-C nyelv egy olyan változata, amely magában foglalja a "modern szemétgyűjtést, szintaktikai fejlesztéseket, [ 5 ] végrehajtási fejlesztéseket [ 6 ] és 64 bites verziót" támogatás". A 2007 októberében kiadott Mac OS X v10.5 tartalmazott egy Objective-C 2.0 fordítót. A GCC 4.6 számos új Objective-C alkalmazást támogat, például deklarált és szintetizált tulajdonságokat, pont szintaxist, gyors felsorolást, opcionális protokollmetódusokat, metódus/protokoll/osztály attribútumokat, osztálykiterjesztéseket és egy új GNUnn Objective-C API-t. [ 7 ]
Szemétgyűjtés
Az Objective 2.0 opcionális konzervatív szemétgyűjtővel rendelkezett. Amikor visszafelé kompatibilitási módban fut , a referenciaszámlálási műveleteket , mint például a „tartás” és a „release” NOP-ra változtatta ( No Operations , egy assembler utasítás, amely azt jelzi, hogy a processzornak nem kell semmit tennie). A szemétgyűjtés engedélyezésekor minden objektumot elküldtek a szemétgyűjtőnek. A C-mutatókat "__strong"-vel lehet minősíteni, hogy a fordító elfogja az írásokat, és így részt vegyen a szemétgyűjtésben. [ 8 ] Egy gyenge nullázási alrendszert is biztosítottak, így a "__gyenge" jelzésű mutatókat nullázták, amikor az objektumot (vagy egyszerűbben a szemétgyűjtő memóriáját) összegyűjtötték. A szemétgyűjtő nem létezett az iOS Objective-C 2.0 megvalósításában. [ 9 ] Az Objective-C szemétgyűjtése alacsony prioritású szálon fut, és leállíthatja a felhasználói eseményeket, azzal a szándékkal, hogy a felhasználói élmény érzékeny maradjon. [ 10 ]
A szemétgyűjtés teljesítményproblémák miatt soha nem volt elérhető iOS-en. Az OS X 10.8-as verziójában elavulttá vált az automatikus referenciaszámlálás (ARC) javára, és a tervek szerint eltávolítják az OS X jövőbeli verziójából. [ 11 ] Az Objective-C iOS 7 - ben ARM64 -en futtatva 19 bitet használ a 64 -ből. -bit szó a hivatkozási szám tárolásához, a címkézett mutató egy formájaként. [ 12 ] [ 13 ]
Tulajdonságok
Az Objective 2.0 új szintaxist vezet be a példányváltozók tulajdonságként való deklarálásához, opcionális attribútumokkal az elérési metódusok létrehozásának konfigurálásához. A tulajdonságok bizonyos értelemben nyilvános példányok változók; vagyis egy példányváltozó tulajdonságként való deklarálása külső osztályoknak (esetleg korlátozott, például csak olvasható ) hozzáférést biztosít az adott tulajdonsághoz. Egy tulajdonság deklarálható "csak olvasható"-ként , és olyan tárolási szemantikával is ellátható, mint a "hozzárendelés" , "másolás" vagy "megőrzés " . Alapértelmezés szerint a tulajdonságok atominak számítanak, ami zárolást eredményez, hogy megakadályozza, hogy egyszerre több szál is hozzáférjen. Egy ingatlan „nem atomi” minősíthető , ami megszünteti ezt a biztosítást.
@interfész személy : NSObject {
@nyilvános
NString * név ;
@magán
int kor ;
}
@ tulajdonság ( másolás ) NSString * név ;
@property ( csak olvasható ) int kor ;
-( id ) startWithAge: ( int ) életkor ;
@vége
A tulajdonságok a @synthesize kulcsszóval valósulnak meg, amely getter (és setter, ha nem csak olvasható) metódusokat generál a tulajdonság deklarációja szerint. Alternatív megoldásként a getter és setter metódusokat explicit módon kell megvalósítani, vagy a @dynamic kulcsszóval jelezhetjük, hogy az accessor metódusokat más módon kell biztosítani. Ha a Clang 3.1 vagy újabb verziójával fordítják le, minden olyan tulajdonság, amely nincs kifejezetten deklarálva a -val @dynamic, nincs bejelölve, readonlyvagy amelyek nem rendelkeznek teljes, a felhasználó által implementált metódusokkal getterés setter, automatikusan @synthesizeimplicit módon deklarálásra kerülnek.
@megvalósító személy
@szintetizáló név ;
-( id ) startWithAge: ( int ) startAge {
self = [ szuper kezdeti ];
if ( self ) {
kor = kezdőKor ; // MEGJEGYZÉS: a példányváltozó közvetlen hozzárendelése, nem a setter tulajdonság }
visszatérő én ;
}
-( int ) kor {
visszatérési kor ;
}
@vége
valueForKey:A tulajdonságok hagyományos üzenetátadási szintaxissal, pontozott jelöléssel, vagy kulcsérték kódolás esetén a / metódusokkal érhetők el setValue:forKey.
Személy * aPerson = [[ Személy kiosztása ] startWithAge : 53 ];
a Személy . név = @"Steve" ; // MEGJEGYZÉS: a pontjelölés a szintetizált settert használja, // ami megegyezik az [aPerson setName: @"Steve"]-vel; NSLog ( @"Hozzáférés üzenettel (%@), pontjelölés (%@ ) , tulajdonságnév ( % @ ) és példányváltozó közvetlen elérése ( % @ ) " , [ aPerson name ] , aPerson . name , [ aPerson valueForKey : @"név" ], aSzemély -> név );
Ahhoz, hogy a pontjelölés használata az Accessor tulajdonságait hívja meg egy példánymetóduson, a "self" kulcsszót kell használni:
-( void ) insertMeWithProperties : ( BOOL ) useGetter {
NSLog ( @"Szia, a nevem %@." , ( useGetter ? self . name : name ));
// MEGJEGYZÉS: getter vs. ivar hozzáférés
}
Egy osztály vagy protokoll tulajdonságai dinamikusan vizsgálhatók .
int i ;
int tulajdonságszámláló = 0 ;
objc_property_t * propertyList = copyPropertyList_class ([ aPerson class ], & propertyCount );
for ( i = 0 ; i < propertyCounter ; i ++ ) {
objc_property_t * thisProperty = propertyList + i ;
const char * propertyName = property_getName ( * thisProperty );
NSLog ( @"A személynek van egy tulajdonsága: '%s'" , propertyName );
}
Nem törékeny példányváltozók
Az Objective-C 2.0 nem törékeny példányváltozókat biztosít a futási környezet által támogatott (például kód létrehozása a 64 bites Mac OS X-hez, valamint az összes iOS-hez). A modern futtatókörnyezetben egy extra torzítási réteget adnak hozzá a példányosítási hozzáférési változókhoz, lehetővé téve a dinamikus linker számára, hogy futás közben módosítsa a példányosítási síkot. Ez a tulajdonság két nagy fejlesztést tesz lehetővé az Objective-C kódban:
- Megszünteti a törékeny bináris interfészek problémáját – a szuperosztályok a bináris kompatibilitás befolyásolása nélkül változtathatják méretüket.
- Lehetővé teszi a tulajdonságok visszafelé kompatibilitását biztosító példányváltozók futás közbeni szintetizálását anélkül, hogy deklarálnák őket az osztályfelületen.
Gyors felsorolás
Ahelyett, hogy egy NSEnumerator objektumot használna vagy egy gyűjteményen keresztüli iterációt jelezne, az Objective-C 2.0 a gyors felsorolás szintaxisát kínálja. Az Objective-C 2.0-ban a következő hurkok funkcionálisan egyenértékűek, de eltérő teljesítményjellemzőkkel rendelkeznek.
// Az NSEnumerator használata
NSEnumerator * enumerator = [ thePeople objectEnumerator ];
Személy * p ;
while (( p = [ enumerator nextObject ]) != nil ) {
NSLog ( @"%@ %i éves." , [ p név ], [ p kor ]);
}
// Indexek használata
for ( int i = 0 ; i < [ the People count ]; i ++ ) {
Személy * p = [ thePeople objectAtIndex : i ] ;
NSLog ( @"%@ %i éves." , [ p név ], [ p kor ]);
}
// Gyors felsorolás használata
a következőhöz: ( Person * p in People ) {
NSLog ( @"%@ %i éves." , [ p név ], [ p kor ]);
}
A gyors felsorolás hatékonyabb kódot generál, mint a szabványos felsorolás, mivel az objektumok felsorolására szolgáló metódushívásokat az NSFastEnumeration protokollt használó mutató aritmetika váltja fel.
Osztálybővítmény
Az osztálybővítmény szintaxisa megegyezik a kategórianév nélküli kategóriadeklarációéval, és a benne deklarált metódusok és tulajdonságok közvetlenül hozzáadódnak az osztályhoz main. Leginkább a kategória alternatívájaként használják metódusok hozzáadására egy osztályhoz anélkül, hogy azokat a nyilvános fejlécekben deklarálnák, azzal az előnnyel, hogy az osztálykiterjesztéseknél a fordító ellenőrzi, hogy az összes privát deklarált metódus valóban megvalósul-e. [ 7 ]
Blokkok
A Blocks az Objective-C (valamint a C és C++ ) nem szabványos kiterjesztése, amely speciális szintaxist használ a lezárások létrehozásához . A blokkokat csak a Mac OS X 10.6 "Snow Leopard" vagy újabb és az iOS 4 vagy újabb, valamint a GNUstep a libobjc2 1.7-tel és a Clang 3.1-es vagy újabb verziójával támogatja. [ 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 += növekmény ;
return ret ;
});
}
int main ( void ) {
IntBlock mycounter = MakeCounter ( 5 , 2 );
printf ( "Első hívás: %d \n " , mycounter ());
printf ( "Második hívás: %d \n " , mycounter ());
printf ( "Harmadik hívás: %d \n " , mycounter ());
/* mert másolták, azt is ki kell adni */
block_release ( mycounter );
return 0 ;
}
/* Kimenet:
Első hívás: 5
Második hívás: 7
Harmadik hívás: 9
*/
Modern Objective-C
Automatikus referenciaszámlálás
Az Automatic Reference Counting ( ARC ) egy fordítási idejű szolgáltatás, amely kiküszöböli a programozóknak a számlálások manuális mentését a retainés segítségével release. [ 11 ] A futásidőben működő szemétgyűjtővel ellentétben az ARC eltávolítja a fiókmegőrzést kezelő külön folyamat többletköltségét. Az ARC és a kézi memóriakezelés nem zárja ki egymást; A fejlesztők továbbra is használhatnak nem ARC kódot azokban a projektekben, amelyekben engedélyezett az ARC, ha letiltják az ARC-t az egyes forráskódokhoz. Az Xcode megpróbálhatja automatikusan frissíteni egy projektet ARC-re.
Literálok
A NeXT és az Apple Obj-C futtatókörnyezetei már régen tartalmaztak egy parancsikont az új karakterláncok létrehozásához, literális szintaxist használva, @"una nueva cadena"valamint elhagyták a CoreFoundation állandókat kCFBooleanTrueés a logikai kCFBooleanFalseváltozóértékeket NSNUmber. Ennek a formátumnak a használata megszabadítja a programozót attól, initWithStringhogy bizonyos műveletek végrehajtása során a leghosszabb vagy hasonló módszereket használja.
Az Apple LLVM 4.0 vagy újabb fordítóprogramjának használatakor tömbök, szótárak és számok (az osztályok és NSArayaz osztályok ) metódusok helyett literális szintaxissal is létrehozhatók. [ 15 ] A literális szintaxis a szimbólumot a -val kombinálva használja , illetve a fent említett osztályok létrehozásához. [ 16 ]
NSDictionaryNSNumber@[]{}()
Példa literálok nélkül:
NSArray * myVector = [ NSArray tömbObjektumokkal : objektum1 , objektum2 , objektum3 , nulla ];
NSDictionary * myDictionary1 = [ NSDictionary dictionaryWithObject : anObject forKey : @"kulcs" ];
NSDictionary * myDictionary2 = [ NSDictionary dictionaryWithObjectsAndKeys : object1 , key1 , object2 , key2 , nil ];
NSNumber * myNumber = [ NSNumber numberWithInt : myInt ];
NSNszám * myNumberSum = [ NSNszámWithInt :( 2 + 3 ) ];
NSNszám * myBooleanNumber = [ NSNszám Logikai értékkel : IGEN ];
Példa literálokkal:
NSArray * myVector = @[ object1 , object2 , object3 ] ;
NSDictionary * myDictionary1 = { @"kulcs" : anObject };
NSDictionary * myDictionary2 = { kulcs1 : objektum1 , kulcs2 : objektum2 };
NSNszám * myNumber = @{ myInt } ;
NSNszám * myNumberSum = @{ 2 + 3 } ;
NSNumber * myBooleanNumber = @YES ;
Azonban ellentétben a karakterlánc-literálokkal, amelyek konstansként vannak lefordítva a futtatható fájlban, ezek a literálok a fent említett metódushívásokkal egyenértékű kódként vannak fordítva. Különösen a memóriahivatkozás-számlálás kézi kezelése során ezek az objektumok önfelszabadítottak, ami különös gondot igényel, ha például statikus függvényváltozókkal vagy más típusú globális változókkal használják őket.
Előfizetések
Az Apple LLVMNSArray 4.0 vagy újabb fordítóprogramjának használatakor a tömbök és szótárak (a és osztályok NSDictionary) módosíthatók alsó indexekkel. [ 15 ] Az alsó indexek segítségével indexekből (vektorokból) vagy kulcsokból (szótárakból) lehet lekérni az értékeket, a változó objektumokkal pedig objektumok indexekké vagy kulcsokká történő beállítására is használhatók. A kódban az alsó indexek szögletes zárójelben vannak ábrázolva [ ]. [ 16 ]
Példák alsó indexek nélkül:
id object1 = [ aVector objectAtIndex : 0 ] ;
id object2 = [ aDictionary objectForKey : @"kulcs" ];
[ aVectorMutable csereObjectAtIndex : 0 withObject : object3 ];
[ aMutableDictionary setObject : object4 forKey : @"kulcs" ];
Példák alsó indexekkel:
id objektum1 = aVektor [ 0 ];
id object2 = aDictionary [ @"kulcs" ];
aMutableVector [ 0 ] = objektum3 ;
aMutableDictionary [ @"kulcs" ] = object4 ;
"Modern" Objective-C szintaxis (1997)
Miután az Apple megvásárolta a NeXT-et, számos kísérlet történt arra, hogy a nyelvet jobban hasonlítsák más meglévő nyelvekhez. Az egyik ilyen próbálkozás az akkoriban "Modern Syntax" néven emlegetett Objective-C bevezetése volt (a meglévő "klasszikus" szintaxissal szemben). A tényleges viselkedésben nem történt változás, ez csak egy alternatív szintaxis volt. A metódus meghívása a következőképpen történt:
object = ( MyClass . alloc ). start ;
tárgyat . firstTag ( param1 , param2 );
És történetesen máshogy írták:
object = [[ MyClass alloc ] init ] ;
[ object firstLabel : param1 secondLabel : param2 ];
Hasonlóképpen, a nyilatkozatok így alakultak:
-( void ) firstLabel ( int param1 , int param2 );
hogy ilyen legyen:
-( void ) firstTag: ( int ) param1 secondTag: ( int ) param2 ;
Ez a "modern" szintaxis nem támogatott a jelenlegi Objective-C nyelvjárásokban.
Portable Object Compiler
A GCC / NeXT / Apple implementációk mellett, amelyek különféle bővítményeket adtak az eredeti Stepstone megvalósításhoz, az Objective-C egy másik ingyenes és nyílt megvalósítása is elérhető, a Protable Object Compiler. [ 17 ] A Portable Object Compiler által megvalósított kiterjesztések készlete eltér a GCC/NeXT/Apple implementációktól; különösen tartalmaz Smalltalk -szerű blokkokat az Objective-C-hez, miközben hiányoznak a protokollok és a kategóriák, két olyan szolgáltatás, amelyet széles körben használnak az OpenStepben és származékaiban. Összességében a POC a nyelvi fejlődés egy régebbi, NeXT előtti szakaszát képviseli, Brad Cox 1991-es könyve szerint.
Tartalmaz egy ObjectPak nevű futásidejű könyvtárat is, amely a Cox eredeti ICPak101 könyvtárán alapul (amely maga a Smalltalk-80 osztálykönyvtárból származik), és gyökeresen különbözik a OneStep FoundationKittől.
GEOS Objective-C
A PC GEOS rendszer a GEOS Objective-C vagy goc néven ismert programozási nyelvet használta ; [ 18 ] Hasonló elnevezésük ellenére a két nyelv általános koncepciójában és a @ jel előtti kulcsszavak használatában is hasonló.
Clang
Az LLVM projekt részét képező Clang fordítócsomag az Objective-C-t és más nyelveket is megvalósítja.
Lásd még
Hivatkozások
- ↑ "Bevezetés a GNUstepbe" (angolul) . Letöltve: 2014. július 10 .
- ^ "A közös műveletek teljesítmény-összehasonlításai" . Archiválva az eredetiből 2009. július 1-jén . Letöltve: 2019. június 19 .
- ↑ "C++ használata Objective-C-vel " . 2008. november 19. Az eredetiből archiválva: 2008. december 31 .. Letöltve: 2014. július 10 .
- ↑ "Clang 3.5 dokumentáció - Együttműködés C++11 lambdákkal " . Letöltve: 2014. július 10 .
- ↑ Dave Vasilevsky (2006. augusztus 10.). "Objective-C 2.0: több nyom " . Archiválva az eredetiből 2009. június 18-án . Letöltve: 2014. július 10 .
- ↑ Dietmar Planitzer (2006. augusztus 9.). "Re: Objective-C 2.0" (angolul) . Archiválva az eredetiből 2010. november 24-én . Letöltve: 2014. július 10 .
- ↑ a b "GCC 4.6 sorozat kiadása: Változások, új funkciók és javítások " . Letöltve: 2014. július 10 .
- ↑ Apple . Garbage Collector API . Letöltve: 2014. július 10 .
- ↑ Apple . "Bevezetés a szemétgyűjtőbe " . Letöltve: 2014. július 10 .
- ↑ Apple (2007. november 6.). "Leopard technológia fejlesztőknek: az Objective-C 2.0 összefoglalója " . Archiválva az eredetiből 2010. július 24-én . Letöltve: 2014. július 10 .
- ↑ a b Apple (2012. július 17.). ARC átmeneti megjegyzések . Letöltve: 2014. július 10 .
- ↑ Mike Ash (2013. szeptember 27.). "ARM64 és te" (angolul) . Letöltve: 2014. július 10 .
- ↑ SealieSoftware.com (2013. szeptember 24.). "Az Objective-C magyarázata: az ISA nem mutató . " Letöltve: 2014. július 10 .
- ↑ Apple (2011. március 8.). "Programozás blokkban" (angolul) . Letöltve: 2014. július 10 .
- ↑ a b Apple . "Programozás az Objective-C-vel: értékek és gyűjtemények " . Letöltve: 2014. július 10 .
- ↑ a b Clang . Objective-C literálok . Letöltve: 2014. július 10 .
- ↑ "Portable Object Compiler " . Letöltve: 2014. július 10 .
- ^ "GEOS SDK " . Letöltve: 2014. július 10 .