Curs Programació MacOSX - Objective-C (II)

Aquí arriba la segona entrega d'aquest curs de programació MacOSX. Ens hem aturat per Setmana Santa per a que els que feu vacances no us ho perdeu. També he de dir que segurament miraré de fer el curs en format de vídeo, per evitar escriure, ja veurem si me'n surto.

Xin  sep  25 març 2008 10:32

Algunes característiques del llenguatge C
=========================================

Per entrar en aquest tema cal que conegueu el llenguatge C, en podeu trobar informació en molts llocs, tant de la xarxa com en llibres. De totes formes en descriurem algunes.

- Totes les ordres acaben amb un punt i coma ";"
- Les funcions tenen la següent sintaxi: nom_funcio(param1, param2, ...);
- Hi ha les següents variables principals: void, char, short, int, long, unsigned XXX, float, double,
- Existeixen els punters, que són adreces a variables (són la part més complicada per als novells). S'indiquen amb el símbol asterisc "*". També hi pot haver punter a punters "**" i punter a punter a punter "***". No us hi trenqueu el cap, a Objective-C no s'utilitzen massa. És millor utilitzar objectes.
- Hi ha les següents sentències de control:
- - if ( condicio ) { codi } else if { codi } else { codi }
- - switch ( variable ) { cas1: codi1 cas2: codi2 defecte: codi }
- - for ( inici; condicio; operacio ) { codi }
- - while ( condicio ) { codi }
- - do { codi } while ( condicio )
- - for ( variable in enumeracio ) { codi } // Nou a Objective-C 2.0
- Les sentències de control queden limitades per claus "{...}"

Bé, si no em deixo res, això és la part més important de la sintaxi del llenguatge de programació C. Ja sé que als que no coneixeu el llenguatge no en tindreu prou, però va bé per poder llegir mínimament el codi que ensenyarem.

Xin  sep  25 març 2008 10:34

Diferències principals amb el llenguatge C
==========================================

Com ja hem dit, el llenguatge Objective-C és una extensió del C, així que tot lo dit en el punt anterior és completament vàlid per a programar, i funciona perfectament.

Tanmateix, si volem aprofitar totes les característiques de programació orientada a objectes que ens ofereix l'Objective-C cal conèixer algunes característiques específiques com són:

Xin  sep  25 març 2008 10:36

Nous tipus
----------
- nil: A C/C++ hi ha la variable NULL (equival a 0). A l'objective-C el seu equivalent és el nil. Però a l'objective-C, el tipus nil és un objecte que pot enviar-se-li missatges (veureu més endavant que els objectes a objective-c no criden funcions ni mètodes, sinó que se li envien missatges als quals responen o no responen). Així, per exemple el següent codi és perfectament possible: [nil missatge]; i no provoca cap error, però tampoc s'executarà res. No pots aconseguir el mateix amb NULL.
- Nil: Com "nil", però en comptes de referir-se a un objecte/instància, és refereix a una classe. No s'acostuma a utilitzar massa.
- BOOL: El llenguatge C no té un tipus oficial de booleà, i en realitat l'Objective-C tampoc. Està inclòs dins de les classes Foundation (anomenades amb la importació de NSObject.h). BOOL a Objective-C té dos estats. YES i NO en comptes de TRUE i FALSE.
- SEL: el tipus "SEL" també anomenat selector és una referència a un missatge del codi compilat. El propi sistema guarda una taula amb tots els selectors de totes les classes, i també dels objecte els quals se'ls ha cridat algun cop. Si volem crear un selector podem utilitzar la directiva @selector(nomDelMissatge:)
- IMP:Un punter a una implementació d'un mètode que retorna (id). No en feu massa cas, no s'utilitza gairebé per a res.
- id: El tipus "id" és un tipus genèric que identifica un objecte, qualsevol objecte pot quedar definit per aquest tipus. Els que coneixeu C++ podeu veure'l com com un equivalen de (void*) un punter sense definir. Aquest s'utilitza moltíssim, tingueu-ne clar el seu ús.
- Class: Tipus que identifica una classe. Tots els objectes tenen una classe. És pot obtenir la classe d'un objecte enviat el missatge "class": Class *classeObjecte = [objecte class]; o directament mitjançant la classe: class *theClass = [NSObject class];
- NSObject*: Això no és realment un tipus, sinó més aviat un exemple de com es defineix un objecte d'una classe. En Objective-C tots els objectes es defineixen com a punter d'una certa classe (excepte del tipus "id" que no cal afegir-li el signe "*" de punter). NSObject és la classe arrel de tots els objectes de les frameworks que utilitzarem i que conté la base de funcionament de tota la framework, intentar crear una classe arrel des de zero seria una feina increïble i et causaria molts problemes. Així que sempre creeu noves classes a partir d'aquesta.
- Classes: Només comentar-vos que a banda de Classes, a l'Objective-C també hi ha Categories i Protocols. Elements que descriurem més endavant. També parlarem de gestió de memòria, la delegació i la presentació que són tècniques més avançades que ens poden facilitar moltes coses, sobre tot les dues primeres.

Xin  sep  25 març 2008 10:37

Noves directives
----------------

Tal com vau veure en l'exemple de l'hola mon, objective-c utilitza #import en comptes de #include. La directiva import equival a la combinació que molts programadors de C utilitzen: #ifndef #define #endif al principi i final de cada fitxer ".h". Així que aconseguir estalviar-nos les tres directives anteriors que ens fan el codi més intel·ligible.

- @class: Aquesta directiva informa al compilador que els noms a continuació són classes vàlides i sense haver d'importar els fitxers de la interfície.
- @interface: Aquesta directiva informa al compilador que el següent codi fina a "@end" serà la definició de la interfície d'una classe, amb la definició de les variables i els mètodes. Tingueu en compte que la interfície és la part visible que els programador coneixeran, això no obstant hi poden haver altres variables i mètodes definits en la implementació.
- @implementation: Aquesta directiva informa al compilador de la implementació d'una classe que acaba amb "@end". En aquesta es poden definir noves variables que quedin ocultes a la interfície i definir els mètodes de la classe.
- @end: Aquesta directiva informa el final d'una directiva prèvia.
- @private: Les variables a partir d'aquí són privades. Només la pròpia classe pot accedir a aquestes variables
- @protected: Les variables a partir d'aquí són protegides. Només la pròpia classe i heretades poden accedir a aquestes variables. És l'estat per defecte si no s'indica res.
- @public: Les variables a partir d'aquí són públiques. Tothom pot accedir a aquestes variables de la forma que és fa una estructura. objecte->variable.
- @protocol: Declara un protocol i els seus mètodes. El seu funcionament és semblant a l'utilitzat en Java. És poden crear objectes "protocol" com si fossin d'una classe particular que han d'implementar les seves funcions, així: NomProtocol *obj. També podem definir un tipus de protocol així: Protocol *counter = @protocol(NomProtocol);
- @try: Directiva per capturar excepcions.
- @catch: Directiva que captura una excepció.
- @finally: Directiva de codi que s'ha d'executar tant si s'ha produït excepció com si no.
- @throw: Directiva per llançar una excepció.
- @synchronized: Directiva per a que un cert codi no pugui executar-se alhora per diversos processos.

Xin  sep  25 març 2008 10:38

Mètode vs Missatge
------------------

Les paraules mètode i missatge s'utilitzen indistintament a Objective-C, encara que els missatges tenen propietats especials. Un missatge pot transmetre's dinàmicament a un altre objecte. Cridar un missatge d'un objecte a Objective-C no significa que l'objecte implementa aquest missatge, només que aquest coneix com respondre-hi ja sigui implementant-lo directament o transmetent el missatge a una altre objecte que sap com fer-ho.

En definitiva si l'objecte no pot respondre al missatge enviat, aquest retornarà "nil" i continuarà el procés com si no hagués passat res.

Xin  sep  25 març 2008 10:38

Enviament de missatges
----------------------

Entrant més a fons en els missatges i les classes, haureu pogut observar en l'exemple de l'Hola Món que hi ha una línia de codi tal com aquesta: NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];. Aquesta línia és la definició d'un objecte i la seva creació.

Podeu observar que s'utilitzen les claudator, una claudator guarda en el seu interior l'enviament d'un missatge on el primer element és l'objecte receptor del missatge i el segon element el missatge i els seus arguments. En l'exemple no hi ha arguments. [receptor missatge];

Xin  sep  25 març 2008 10:38

Missatges amb paràmetres
------------------------

Els missatges que disposen de paràmetres queden definits per dos punts cada paràmetre, així un missatge que hagi de respondre a un paràmetre acabarà amb dos punts, seguits dels quals hi haurà el paràmetre, així: [receptor missatgeAmbParam:param];

Si hi hagués més d'un paràmetre hi hauria tants "dos punts" com paràmetres, així: [receptor missatgeAmbParam1:param1 iParam2:param2];

Mirem con quedarien definits en la declaració de la classe:

+ (id) missatge;
- (void) missatgeAmbParam:(int)elParam;
- (NSArray*) missatgeAmbParam1:(int)elParam1 iParam2:(NSObject*)elParam2;
- (void) missatgeAmbVector:(int)laX :(int)laY :(int)laZ;

Podeu veure diferents elements diferenciats. El primer són els signes (-) i (+) que com veureu en el capítol de les classes indiquen si el missatge és de classe "+" o d'objecte "-". El segon element indica el tipus de retorn, que pot ser qualsevol dels tipus permesos. A partir d'aquí hi ha el nom del missatge ( "missatge", "missatgeAmbParam:", "missatgeAmbParam1:iParam2:", "missatgeAmbVector:::" ), podeu veure que el nom final del missatge no conté el tipus ni el nom del paràmetre ni el tipus, simplement el nom del missatge i els doble punts necessaris. Si mai heu de crear un selector "SEL" caldrà que utilitzeu el nom que heu vist abans (sense cometes). Així:
SEL metode0 = @selector(missatge);
SEL metode1 = @selector(missatgeAmbParam:);
SEL metode2 = @selector(missatgeAmbParam1:iParam2:);
SEL metode3 = @selector(missatgeAmbVector:::);

També podeu observar que l'últim missatge conté els tres punts junts, això és completament vàlid, no és obligatori que la resta de paràmetres continguin text abans dels dos punts, encara que potser si el tenen és més entenedor.

Cal també recordar que en una mateixa classe no pot haver-hi dos missatge amb el mateix nom. A diferència de C, no existeix la sobre-escriptura de mètodes amb paràmetres de diferents tipus. Això és així, perquè el sistema realitza l'enviament dels mètodes via el seu nom i de forma dinàmica, mai es té en compte el tipus de paràmetre.

Xin  sep  25 març 2008 10:39

Selecciona'l abans d'enviar el commentari