| Objective-C |
|---|
| Desarrollador(es) |
|---|
| ? |
| Información general |
|---|
| Extensiones comunes | .h, .m, .mm, .M |
|---|
| Paradigma | orientado a objetos |
|---|
| Apareció en | 1980 |
|---|
| Diseñado por | Brad Cox yTom Love |
|---|
| Última versión estable | 2.0 |
|---|
| Sistema de tipos | estático,dinámico, débil |
|---|
| Implementaciones | Clang,GCC |
|---|
| Dialectos | Objective-J,TOM |
|---|
| Influido por | C,Smalltalk |
|---|
| Ha influido a | Groovy,Java,Nu,Objective-C++,Swift, |
|---|
|
Objective-C es unlenguaje de programaciónorientado a objetos creado como un superconjunto deC para que implementase un modelo de objetos parecido al deSmalltalk. Originalmente fue creado por Brad Cox y la corporación StepStone en 1980. En 1988 fue adoptado comolenguaje de programación deNEXTSTEP y en 1992 fue liberado bajo licenciaGPL para elcompiladorGCC. Actualmente se usa como un lenguaje principal de programación paraMac OS X,iOS yGNUstep, además deSwift.
A principios de los 80, elsoftware se desarrollaba usandoprogramación estructurada. La programación estructurada se estableció para ayudar a dividir los programas en pequeñas partes, haciendo más fácil el desarrollo cuando la aplicación se volvía muy grande. Sin embargo, como los problemas seguían creciendo al pasar el tiempo, la programación estructurada se volvió compleja dado el desorden de algunos programadores para invocar instrucciones repetitivamente, llevando acódigo spaghetti y dificultando la reutilización de código.
Muchos vieron que la programación orientada a objetos sería la solución al problema. De hecho, Smalltalk ya tenía solucionados muchos de estos problemas: algunos de los sistemas más complejos en el mundo funcionaban gracias a Smalltalk. Pero Smalltalk usaba una máquina virtual, lo cual requería mucha memoria para esa época, y era demasiado lento.
Objective-C fue creado principalmente por Brad Cox y Tom Love a inicios de los 80 en su compañía Stepstone. Ambos fueron iniciados en Smalltalk mientras estaban en el Programming Technology Center de ITT en 1981. Cox se vio interesado en los problemas de reutilización en el desarrollo desoftware. Se dio cuenta de que un lenguaje como Smalltalk sería imprescindible en la construcción de entornos de desarrollo potentes para los desarrolladores en ITI Corporation. Cox empezó a modificar el compilador de C para agregar algunas de las capacidades de Smalltalk. Pronto tuvo una extensión para añadir la programación orientada a objetos a C la cual llamó «OOPC»,Object-Oriented Programming in C. Love mientras tanto, fue contratado por Shlumberger Research en 1982 y tuvo la oportunidad de adquirir la primera copia de Smalltalk-80, lo que influyó en su estilo como programador.
Para demostrar que se hizo un progreso real, Cox mostró que para hacer componentes desoftware verdaderamente intercambiables solo se necesitaban unos pequeños cambios en las herramientas existentes. Específicamente, estas necesitaban soportar objetos de manera flexible, venir con un conjunto debibliotecas que fueran utilizables, y permitir que el código —y cualquier recurso necesitado por el código— pudiera ser empaquetado en un formatomultiplataforma.
Cox y Love luego fundaron una nueva empresa, Productivity Products International —PPI—, para comercializar su producto: un compilador de Objective-C con un conjunto de bibliotecas potentes.
En 1986, Cox publicó la principal descripción de Objective-C en su forma original en el libroObject-Oriented Programming, An Evolutionary Approach. Aunque él fue cuidadoso en resaltar que hay muchos problemas de reutilización que no dependen del lenguaje, Objective-C frecuentemente fue comparado detalladamente con otros lenguajes.
Popularización mediante NeXT
[editar]En 1988,NeXT licenció el Objective-C de StepStone, nuevo nombre de PPI, dueña de la marca Objective-C, y extendió el compiladorGCC para dar soporte a Objective-C al mismo tiempo que desarrolló las librerías AppKit y Foundation Kit sobre las que se basaron la interfaz de usuario y la interfaz de creación deNeXTStep. Mientras que las estaciones de trabajo de NeXT no consiguieron hacer un gran impacto en el mercado, las herramientas fueron ampliamente alabadas en la industria. Esto llevó a NeXT a abandonar la producción de hardware y enfocarse en las herramientas desoftware, vendiendo NeXTstep —y OpenStep— como una plataforma para la programación a medida.
El trabajo para extenderGCC fue liderado por Steve Naroff, que se unió a NeXT proveniente de StepStone. Los cambios del compilador fueron puestos a disposición bajo términos de licenciaGPL, pero no las librerías de tiempo de ejecución, dejando la contribución de código abierto inutilizable para el público general. Esto llevó a que otras compañías desarrollaran esas librerías bajo licencias de código abierto. Más tarde, Steve Naroff fue también un colaborador principal al trabajo de Apple de construir la interfaz de Objective-CClang.
El proyectoGNU comenzó a trabajar en su implementación de Cocoa comosoftware libre, llamadoGNUstep y basado en el estándar de OpenStep.[1] Dennis Glatting escribió el primersistema en tiempo de ejecución de GNU Objective-C en 1992. El sistema GNU Objective-C, que ha sido usado desde 1993, es uno de los desarrollados por Kresten Krab Thorup cuando era un estudiante universitario enDinamarca. Thorup también trabajó en NeXT desde 1993 hasta 1997.
Desarrollo de Apple y Swift
[editar]Tras adquirir NeXT en 1996,Apple empleó OpenStep en su nuevosistema operativo,Mac OS X. Este incluía Objective-C y la herramienta de desarrollo basada en Objective-C de NeXT,Project Builder, que luego se ha expandido y ahora se conoce porXcode, así como la herramienta de diseño de interfaz, Interface Builder. La mayoría de la actualCocoa API de Apple está basada en objetos de interfaz de OneStep, y es el entorno de desarrollo de Objective-C más usado para desarrollo activo.
En laWWDC de 2014, Apple anunció planes para reemplazar a Objective-C en el desarrollo de Cocoa por el nuevo lenguajeSwift, que es llamado «Objective-C sin la C».
Objective-C consiste en una capa muy fina situada por encima de C, y además es unestrictosuperconjunto de C. Esto hace posible compilar cualquier programa escrito en C con un compilador de Objective-C, y también puede incluir libremente código en C dentro de una clase de Objective-C.
Esto es, para escribir el programa clásico "Hola Mundo" para correr en consola, se puede utilizar el siguiente código:
#import <stdio.h>intmain(intargc,constchar*argv[]){printf("Hola Mundo\n");return0;}El código anterior se diferencia de un código en C común por la primera instrucción#import, que difiere del#include del C clásico, pero la funciónprintf("") es puramente C. La función propia de Objective-C para imprimir unacadena de caracteres en consola esNSLog(@"") utilizándola, el código anterior quedaría de la siguiente manera:
intmain(intargc,constchar*argv[]){NSLog(@"Hola Mundo\n");return0;}La sintaxis de objetos de Objective-C deriva deSmalltalk. Toda la sintaxis para las operaciones no orientadas a objetos, incluyendo variables primitivas, pre-procesamiento, expresiones, declaración de funciones y llamadas a funciones, son idénticas a las de C, mientras que la sintaxis para las características orientadas a objetos es una implementación similar a la mensajería de Smalltalk.
El modelo de programación orientada a objetos de Objective-C se basa en enviar mensajes a instancias de objetos. Esto es diferente al modelo de programación al estilo deSimula, utilizado porC++ y esta distinción es semánticamente importante. En Objective-C uno nollama a un método; unoenvía un mensaje, y la diferencia entre ambos conceptos radica en cómo el código referido por el nombre del mensaje o método es ejecutado. En un lenguaje al estilo Simula, el nombre del método es en la mayoría de los casos atado a una sección de código en la clase objetivo por el compilador, pero enSmalltalk y Objective-C, el mensaje sigue siendo simplemente un nombre, y es resuelto en tiempo de ejecución: el objeto receptor tiene la tarea de interpretar por sí mismo el mensaje. Una consecuencia de esto es que el mensaje del sistema que pasa no tiene chequeo de tipo: el objeto al cual es dirigido el mensaje —conocido comoreceptor— no está inherentemente garantizado a responder a un mensaje, y si no lo hace, simplemente lo ignora y retorna un puntero nulo.
Enviar el mensajemethod al objeto apuntado por el punteroobj requeriría el siguiente código en C++:
mientras que en Objective-C se escribiría como sigue:
Ambos estilos de programación poseen sus fortalezas y debilidades. La POO al estilo Simula permite herencia múltiple y rápida ejecución utilizando vinculación entiempo de compilación siempre que sea posible, pero no soporta vinculación dinámica por defecto. Esto fuerza a que todos los métodos posean su correspondiente implementación, al menos que sean virtuales. Aun así, se requiere una implementación del método para efectuar la llamada. La POO al estilo Smalltalk permite que los mensajes no posean implementación - por ejemplo, toda una colección de objetos pueden enviar un mensaje sin temor a producir errores en tiempo de ejecución. El envío de mensajes tampoco requiere que un objeto sea definido en tiempo de compilación. Ver más abajo la seccióntipado dinámico para más ventajas de la ligadura dinámica.
Sin embargo, se debe notar que debido a la sobrecarga de la interpretación de los mensajes, un mensaje en Objective-C toma, en el mejor de los casos, tres veces más tiempo que una llamada a un método virtual en C++.[2]
Interfaces e implementaciones
[editar]Objective-C requiere que la interfaz e implementación de una clase estén en bloques de código separados. Por convención, la interfaz es puesta en un archivo cabecera y la implementación en un archivo de código; los archivos cabecera, que normalmente poseen el sufijo .h, son similares a los archivos cabeceras de C; los archivos de implementación —método—, que normalmente poseen el sufijo .m, pueden ser muy similares a los archivos de código de C.
La interfaz de la clase es usualmente definida en el archivo cabecera. Una convención común consiste en nombrar al archivo cabecera con el mismo nombre de la clase. La interfaz para la claseClase debería, así, ser encontrada en el archivoClase.h.
La declaración de la interfaz de la forma:
@interfaceclassname :superclassname{// instance variables}+classMethod1;+(return_type)classMethod2;+(return_type)classMethod3:(param1_type)parameter_varName;-(return_type)instanceMethod1:(param1_type)param1_varName:(param2_type)param2_varName;-(return_type)instanceMethod2WithParameter:(param1_type)param1_varNameandOtherParameter:(param2_type)param2_varName;@endLos signosmás denotan métodos de clase, los signosmenos denotan métodos de instancia. Los métodos de clase no tienen acceso a las variables de la instancia.
Si usted viene de C++, el código anterior es equivalente a algo como esto:
classclassname:superclassname{public:// instance variables// Class (static) functionsstaticvoid*classMethod1();staticreturn_typeclassMethod2();staticreturn_typeclassMethod3(param1_typeparameter_varName);// Instance (member) functionsreturn_typeinstanceMethod1(param1_typeparam1_varName,param2_typeparam2_varName);return_typeinstanceMethod2WithParameter(param1_typeparam1_varName,param2_typeparam2_varName=default);};Note queinstanceMethod2WithParameter demuestra la capacidad de nombrado de parámetro de Objective-C para la cual no existe equivalente directo en C/C++.
Los tipos de retorno pueden ser cualquier tipo estándar de C, un puntero a un objeto genérico de Objective-C, o un puntero a un tipo específico así comoNSArray *,NSImage *, oNSString *. El tipo de retorno por defecto es el tipo genéricoid de Objective-C.
Los argumentos de los métodos comienzan con dos puntos seguidos por el tipo de argumento esperado en los paréntesis seguido por el nombre del argumento. En algunos casos (por ej. cuando se escriben APIs de sistema) es útil agregar un texto descriptivo antes de cada parámetro.
-(void)setRangeStart:(int)startEnd:(int)end;-(void)importDocumentWithName:(NSString*)namewithSpecifiedPreferences:(Preferences*)prefsbeforePage:(int)insertPage;
La interfaz únicamente declara la interfaz de la clase y no los métodos en sí; el código real es escrito en la implementación. Los archivos de implementación (métodos) normalmente poseen la extensión.m.
@implementationclassname+classMethod{// implementation}-instanceMethod{// implementation}@endLos métodos son escritos con sus declaraciones de interfaz. Comparando Objective-C y C:
-(int)method:(int)i{return[selfsquare_root:i];}intfunction(inti){returnsquare_root(i);}La sintaxis admite pseudo-nombrado de argumentos.
-(int)changeColorToRed:(float)redgreen:(float)greenblue:(float)blue[myColorchangeColorToRed:5.0green:2.0blue:6.0];
La representación interna de este método varía entre diferentes implementaciones de Objective-C. Si myColor es de la claseColor, internamente, la instancia del método-changeColorToRed:green:blue: podría ser etiquetada como_i_Color_changeColorToRed_green_blue. Lai hace referencia a una instancia de método, acompañado por los nombres de la clase y el método, y los dos puntos son reemplazados por guiones bajos. Como el orden de los parámetros es parte del nombre del método, éste no puede ser cambiado para adaptarse al estilo de codificación.
De todos modos, los nombres internos de las funciones son raramente utilizadas de manera directa, y generalmente los mensajes son convertidos a llamadas de funciones definidas en la librería en tiempo de ejecución de Objective-C – el método que será llamado no es necesariamente conocido en tiempo de vinculación: la clase del receptor, el objeto que envió el mensaje, no necesita conocerlo hasta el tiempo de ejecución.
Una vez que una clase es escrita en Objective-C, puede ser instanciada. Esto se lleva a cabo primeramente alojando la memoria para el nuevo objeto y luego inicializándolo. Un objeto no es completamente funcional hasta que ambos pasos sean completados. Esos pasos típicamente se logran con una simple línea de código:
MyObject*o=[[MyObjectalloc]init];
La llamada a alloc aloja la memoria suficiente para mantener todas las variables de instancia para un objeto, y la llamada a init puede ser anulada para establecer las variables de instancia con valores específicos al momento de su creación. El método init es escrito a menudo de la siguiente manera:
-(id)init{self=[superinit];if(self){ivar1='''value1''';ivar2=value2;...}returnself;}Objective-C fue extendido enNeXT para introducir el concepto deherencia múltiple de la especificación, pero no la implementación, a través de la introducción deprotocolos. Este es un modelo viable, ya sea como una clase base abstracta multi-heredada en C++, o como una «interfaz», como enJava oC#. Objective-C hace uso de protocolosad hoc, llamadosprotocolos informales, y el compilador debe cumplir los llamadosprotocolos formales.
Objective-C, al igual que Smalltalk, puede usartipado dinámico: un objeto puede recibir un mensaje que no está especificado en su interfaz. Esto se permite para incrementar la flexibilidad, ya que permite a un objeto "capturar" un mensaje y enviarlo a otro objeto diferente que pueda responder a ese mensaje apropiadamente, o del mismo modo reenviar el mensaje a otro objeto. Este comportamiento es conocido comoreenvío de mensajes odelegación (ver más abajo). Alternativamente, un manejo de error puede ser usado en caso de que el mensaje no pueda ser reenviado. Si un objeto no reenvía un mensaje, lo responde o maneja un error entonces el sistema generará una excepción en tiempo de ejecución. Si los mensajes son enviados anil, el puntero de objetos nulo, serán ignorados silenciosamente o elevarán una excepción genérica, dependiendo de las opciones del compilador.
La información tipada estáticamente puede ser añadida opcionalmente a variables. Esta información es luego comprobada a la hora de compilar. En las siguientes cuatro declaraciones se proveen tipos de información crecientemente específicos. Estas declaraciones son equivalentes en el tiempo de ejecución, pero la información adicional permite al compilador el avisar al programador si el argumento pasado no encaja con el tipo especificado.
-(void)setMyValue:(id)foo;
En la declaración anterior,foo puede ser de cualquier clase.
-(void)setMyValue:(id<NSCopying>)foo;
En la declaración anterior,foo puede ser una instancia de cualquier clase que satisfaga al protocoloNSCopying.
-(void)setMyValue:(NSNumber*)foo;
En la declaración anterior,foo debe ser una instancia de la claseNSNumber.
-(void)setMyValue:(NSNumber<NSCopying>*)foo;
En la declaración anterior,foo debe ser una instancia de la claseNSNumber, y debe satisfacer al protocoloNSCopying.
Objective-C permite el envío de un mensaje a un objeto que puede no responder. En lugar de responder o simplemente ignorar el mensaje, un objeto puede reenviar el mensaje a otro objeto que pueda responderlo. El reenvío puede ser usado para simplificar la implementación de ciertospatrones de diseño, como elobserver o elproxy.
El tiempo de ejecución de Objective-C especifica un par de métodos enObject:
-(retval_t)forward:(SEL)selargs:(arglist_t)args;// con GCC-(id)forward:(SEL)selargs:(marg_list)args;// con sistemas NeXT/Apple
-(retval_t)performv:(SEL)selargs:(arglist_t)args;// con GCC-(id)performV:(SEL)selargs(marg_list)args;// con sistemas NeXT/Apple
Un objeto que desee implementar el reenvío solamente necesita sobreescribir el método de reenvío con un nuevo método que defina el comportamiento de reenvío. El método de acciónperformv:: no necesita ser sobreescrito, ya que este método meramente realiza una acción basada en el selector y los argumentos. El tipoSEL es el tipo de mensajes en Objective-C.
Nota: en openStep, Cocoa y GNUstep, los espacios de trabajo de Objective-C comúnmente usados, no hay que usar la claseObject. el método- (void)forwardInvocation:(NSInvocation *)anInvocation de la claseNSObject es usado para realizar el reenvío.
Aquí hay un ejemplo de un programa que demuestra las bases del reenvío.
- Forwarder.h
# import <objc/Object.h>@interfaceForwarder :Object{idrecipient;// El objeto al que queremos reenviar el mensaje.}// Métodos de acceso-(id)recipient;-(id)setRecipient:(id)_recipient;@end- Forwarder.m
# import "Forwarder.h"@implementationForwarder-(retval_t)forward:(SEL)selargs:(arglist_t)args{/* * Comprueba si el receptor responde al mensaje. * Esto puede ser o no deseable, por ejemplo, si un receptor * a su vez no responde el mensaje, podría reenviarlo él mismo. */if([recipientrespondsToSelector:sel]){return[recipientperformv:selargs:args];}else{return[selferror:"El receptor no responde"];}}-(id)setRecipient:(id)_recipient{[recipientautorelease];recipient=[_recipientretain];returnself;}-(id)recipient{returnrecipient;}@end- Recipient.h
# import <objc/Object.h>// Un simlpe objeto receptor.@interfaceRecipient :Object-(id)hola;@end
- Recipient.m
# import "Recipient.h"@implementationRecipient-(id)hola{printf("El receptor dice hola!\n");returnself;}@end- main.m
# import "Forwarder.h"# import "Recipient.h"intmain(void){Forwarder*forwarder=[Forwardernew];Recipient*recipient=[Recipientnew];[forwardersetRecipient:recipient];// Elige el receptor./* * Véase que el reenviante no responda al saludo! Será reenviado. * Todos los métodos no reconocidos serán reenviados al receptor * (si el receptor los responde, como se dice en el Forwarder) */[forwarderhello];[recipientrelease];[forwarderrelease];return0;}Cuando se compila congcc, el compilador reporta:
$ gcc -x objective-c -Wno-import Forwarder.m Recipient.m main.m -lobjc
main.m: In function `main':
main.m:12: warning: `Forwarder' no responde a `hola'
$
El compilador reporta lo comentando antes, queForwarder no responde a mensajeshola. En esta circunstancia, es seguro ignorar el aviso ya que el reenvío fue implementando. La ejecución del programa produce esta salida:
& ./a.out
El receptor dice hola!
Variantes del lenguaje
[editar]Objective-C++ es una variante del lenguaje aceptada por la interfaz delGNU Compiler Collection yClang, que puede compilar archivos de código fuente que usen una combinación de sintaxis de C++ y Objective-C. Objective-C++ añade a C++ las extensiones que Objective-C añade a C. Como no se hace nada para unificar la semántica detrás de las características de varios lenguajes, existen ciertas restricciones:
- Una clase de C++ no puede derivar de una clase de Objective-C y viceversa.
- Espacios de nombres de C++ no pueden ser declarados dentro de una declaración de Objective-C.
- Las declaraciones de Objective-C deben aparecer de manera global, no dentro de una declaración de C++.
- Las clases de Objective-C no pueden tener instancias variables de clases de C++ que no tengan un constructor por defecto o que tengan uno o más métodos virtuales, pero los punteros a objetos de C++ pueden ser usados como instancias variables sin restricción, se asignan en el método -init.
- Las semánticas "por valor" de C++ no pueden ser aplicadas a objetos de Objective-C, que solamente son accesibles mediante punteros.
- Una declaración de Objective-C no puede estar dentro de una plantilla de declaración de C++ y viceversa. Sin embargo, los tipos de Objective-C, comoClassname *, pueden ser usados como parámetros de plantillas de C++.
- Elmanejo de excepciones de Objective-C y C++ es distinto; cada lenguaje solamente puede manejar excepciones propias. Esto es mitigado en recientes versiones o bien reemplazando completamente las exceptiones de Objective-C por excepciones de C++, como hace Apple, o parcialmente cuando está enlacada la librería de Objective-C++, GNUstep libobjc2.
- Hay que tener cuidado ya que las llamadas al destructor de las excepciones en tiempo de ejecución de Objective-C y C++ no coinciden. Por ejemplo, un destructor de C++ no será llamado cuando una excepción de Objective-C sale del alcance de un objeto de C++. Las nuevas versiones de 64 bits solucionan esto mediante la introducción de interoperabilidad con las excepciones de C++ en este sentido.[3]
- Los blocks de Objective-C y las lambdas de C++11 son entidades distintas, sin embargo un block es generado transparentemente en Mac OS X cuando se pasa una lambda donde se espera un block.[4]
En laWorldwide Developers Conference de 2006, Apple anunció el lanzamiento de "Objective-C 2.0", una revisión del lenguaje Objective-C para incluir "una recolección de basura moderna, mejoras de sintaxis,[5] perfeccionamiento de la ejecución[6] y soporte para 64 bits".Mac OS X v10.5, lanzado en octubre de 2007, incluía un compilador de Objective-C 2.0.GCC 4.6 soporta muchas aplicaciones nuevas de Objective-C, como las propiedades declaradas y sintetizadas, sintaxis de puntos, enumeración rápida, métodos de protocolo opcionales, atributos de método/protocolo/clase, extensiones de clase y una nueva API de GNUnn Objective-C.[7]
Objective 2.0 contaba con unrecolector de basura conservativo opcional. Cuando se ejecutaba en modo deretrocompatibilidad, cambiaba las operaciones deconteo de referencias como «retener» y «liberar» en NOPs, o seaNo operaciones, instrucción de ensamblador que indica que el procesador no tiene que hacer nada. Todos los objetos eran sometidos al recolector de basura cuando la recolección de basura estaba habilitada. Los punteros de C podían ser cualificados con "__strong" para provocar la intercepción de escritura del compilador y así participar en la recolección de basura.[8] Un subsistema débil de puesta a cero también era provisto de tal manera que los punteros marcados con "__weak" eran puestos a cero cuando el objeto —o más fácilmente, la memoria del recolector de basura— es recolectado. El recolector de basura no existía en la implementación de Objective-C 2.0 de iOS.[9] La recolección de basura en Objective-C se ejecuta en un hilo de baja prioridad y puede detener eventos del usuario, con la intención de mantener la experiencia del usuario receptiva.[10]
La recolección de basura nunca estuvo disponible en iOS debido a problemas de rendimiento. Fue despreciado en la versión 10.8 de OS X en favor del Conteo de Referencias Automático, oAutomatic Reference Counting —ARC— en inglés, y está programado que se elimine en una futura versión de OS X.[11] Objective-C eniOS 7 ejecutado enARM64 usa 19 bits de una palabra de 64 bits para almacenar el conteo de referencias, como una forma de puntero etiquetado.[12][13]
Objective 2.0 introduce una nueva sintaxis para declarar variables de instancia como propiedades, con atributos opcionales para configurar la generación de métodos de acceso. Las propiedades son, en cierto sentido, variables de instancia públicas; esto es, declarar una variable de instancia como una propiedad provee a clases externas de acceso (posiblemente limitado, como por ejemplosolo lectura) a esa propiedad. Una propiedad puede ser declarada como "readonly" (solo lectura) y puede ser provista de semántica de almacenamiento como "assign" (asignar), "copy" (copiar) o "retain" (retener). Por defecto, las propiedades son consideradas atómicas, que resulta en un seguro para prevenir a múltiples hilos que accedan a ella al mismo tiempo. Una propiedad puede ser declarada como "nonatomic" (no atómica), que elimina este seguro.
@interfacePersona :NSObject{@publicNSString*nombre;@privateintedad;}@property(copy)NSString*nombre;@property(readonly)intedad;-(id)iniciarConEdad:(int)edad;@endLas propiedades son implementadas mediante la palabra clave @synthesize, que genera los métodos getter (y setter, si no son de solo lectura) de acuerdo a la declaración de la propiedad. Alternativamente, los métodos getter y setter deben ser implementados explícitamente, o la palabra clave @dynamic puede ser usada para indicar que los métodos de acceso deben ser provistos por otros medios. Cuando se compila usando Clang 3.1 o superior, todas las propiedades que no estén explícitamente declaradas con@dynamic, no estén marcadasreadonly o no tengan los métodos completos implementados por el usuariogetter ysetter, serán automáticamente declaradas@synthesize de manera implícita.
@implementationPersona@synthesizenombre;-(id)iniciarConEdad:(int)edadInicial{self=[superinicial];if(self){edad=edadInicial;// NOTA: asignación directo de la variable de instancia, no propiedad setter}returnself;}-(int)edad{returnedad;}@endLas propiedades pueden ser accedidas usando la sintaxis tradicional de paso de mensajes, notació por puntos o, en Codificación Key-Value, mediante los métodosvalueForKey:/setValue:forKey.
Persona*unaPersona=[[Personaalloc]iniciarConEdad:53];unaPersona.nombre=@"Steve";// NOTA: la notación por puntos, usa el setter sintetizado,// equivalente a [unaPersona setNombre: @"Steve"];NSLog(@"Acceso por mensaje (%@), notación por puntos(%@),nombredepropiedad(%@)yaccesodirectoalavariabledeinstancia(%@)",[unaPersonanombre],unaPersona.nombre,[unaPersonavalueForKey:@"nombre"],unaPersona->nombre);
Para que el uso de notación por puntos invoque a las propiedades de acceso en un método de instancia, la palabra clave "self" debe ser usada:
-(void)presentarmeConPropiedades:(BOOL)useGetter{NSLog(@"Hola, mi nombre es %@.",(useGetter?self.nombre:nombre));// NOTA: getter vs. acceso ivar}Una clase o las propiedades de protocolo pueden serintrospeccionadas dinámicamente.
inti;intcontadorPropiedades=0;objc_propiedad_t*listaPropiedades=clase_copiarListaPropiedades([unaPersonaclass],&contadorPropiedades);for(i=0;i<contadorPropiedades;i++){objc_propiedad_t*estaPropiedad=listaPropiedades+i;constchar*nombrePropiedad=propiedad_getNombre(*estaPropiedad);NSLog(@"Persona tiene una propiedad: '%s'",nombrePropiedad);}Variables de instancia no frágiles
[editar]Objective-C 2.0 provee de variables de instancia no frágiles soportadas por el entorno de ejecución (por ejemplo, creando código para un Mac OS X de 64 bits así como código para todos los iOS). Bajo el entorno de ejecución moderno, una capa extra de sesgo es añadida para instanciar variables de acceso, permitiendo al enlazador dinámico ajustar el plano de instanciaciones en tiempo de ejecución. Esta propiedad permite dos grandes mejoras en el código Objective-C:
- Elimina el problema de la fragilidad de interfaces binarias - las superclases pueden cambiar su tamaño sin afectar a la compatibilidad binaria.
- Permite que las variables de instancia que proveenretrocompatibilidad para las propiedades puedan ser sintetizadas en el tiempo de ejecución sin que estén declaradas en la interfaz de la clase.
En lugar de usar un objeto NSEnumerator o indicar la iteración a lo largo de una colección, Objective-C 2.0 ofrece la sintaxis de enumeración rápida. En Objective-C 2.0, los siguientes bucles son funcionalmente equivalentes, pero tienen diferentes características de rendimiento.
// Usando NSEnumeratorNSEnumerator*enumerador=[laGenteobjectEnumerator];Persona*p;while((p=[enumeradornextObject])!=nil){NSLog(@"%@ tiene %i años.",[pnombre],[pedad]);}// Usando índicesfor(inti=0;i<[laGentecount];i++){Persona*p=[laGenteobjectAtIndex:i];NSLog(@"%@ tiene %i años.",[pnombre],[pedad]);}// Using enumeración rápidafor(Persona*pinlaGente){NSLog(@"%@ tiene %i años.",[pnombre],[pedad]);}La enumeración rápida genera código más eficiente que la enumeración estándar porque las llamadas a los métodos para enumerar objetos son reemplazadas por aritmética de punteros usando el protocolo NSFastEnumeration.
Una extensión de clase tiene el mismo sintaxis que una declaración de categoría sin nombre de categoría y los métodos y propiedades declarados en ella son añadidos directamente a la clasemain. Es sobre todo usado como una alternativa a una categoría el añadir métodos a una clase sin declararlos en las cabeceras públicas, con la ventaja de que para las extensiones de clase el compilador comprueba que todos los métodos declarados privadamente son implementados realmente.[7]
Blocks es una extensión no estándar para Objective-C (así como paraC yC++) que usa una sintaxis especial para crearclausuras. Blocks solo está soportado enMac OS X 10.6 "Snow Leopard" o superior y eniOS 4 o superior, así como en GNUstep con libobjc2 1.7 y compilado conClang 3.1 o superior.[14]
#include<stdio.h>#include<Block.h>typedefint(^IntBlock)();IntBlockMakeCounter(intstart,intincrement){__blockinti=start;returnBlock_copy(^{intret=i;i+=increment;returnret;});}intmain(void){IntBlockmycounter=MakeCounter(5,2);printf("First call: %d\n",mycounter());printf("Second call: %d\n",mycounter());printf("Third call: %d\n",mycounter());/* because it was copied, it must also be released */Block_release(mycounter);return0;}/* Output:First call: 5Second call: 7Third call: 9*/Automatic Reference Counting
[editar]Automatic Reference Counting (Conteo Automático de Referencias, ARC) es una característica del tiempo de compilación que elimina la necesidad de que los programadores tengan que guardar manualmente cuentas usandoretain yrelease.[11] Al contrario que elrecolector de basura, que funciona en tiempo de ejecución, el ARC elimina la sobrecarga de un proceso separado al gestionar la retención de las cuentas. El ARC y el manejo manual de memoria no son mutualmente excluyentes; los programadores pueden continuar usando código no ARC en proyectos que tienen el ARC activado mediante la desactivación del ARC para códigos fuente individuales. Xcode también puede tratar de actualizar automáticamente un proyecto a ARC.
Los entornos de ejecución NeXT y Apple Obj-C incluyeron hace tiempo un atajo para crear nuevas cadenas, usando la sintaxis literal@"una nueva cadena" y también desecharon las constantes de CoreFoundationkCFBooleanTrue ykCFBooleanFalse por la variableNSNUmber con valores booleanos. Al usar este formato se libera al programador de usar el más largoinitWithString o métodos similares al hacer ciertas operaciones.
Cuando se usa el compilador de AppleLLVM 4.0 o superior, vectores, diccionarios y números (las clasesNSAray,NSDictionary yNSNumber) pueden ser también creados usando sintaxis literal en lugar de métodos.[15] La sintaxis literal usa el símbolo@ combinado con[],{} o() para crear las clases mencionadas anteriormente, respectivamente.[16]
Ejemplo sin literales:
NSArray*miVector=[NSArrayarrayConObjectos:objeto1,objeto2,objeto3,nil];NSDictionary*miDiccionario1=[NSDictionarydiccionarioConObjeto:unObjetoforKey:@"llave"];NSDictionary*miDiccionario2=[NSDictionarydiccionarioConObjetosYLlaves:objeto1,llave1,objeto2,llave2,nil];NSNumber*miNumero=[NSNumbernumeroConInt:miInt];NSNumber*miNumeroSuma=[NSNumbernumeroConInt:(2+3)];NSNumber*miNumeroBooleano=[NSNumbernumeroConBooleano:YES];
Ejemplo con literales:
NSArray*myVector=@[objeto1,objeto2,objeto3];NSDictionary*miDiccionario1={@"llave":unObjeto};NSDictionary*miDiccionario2={llave1:objeto1,llave2:objeto2};NSNumber*miNumero=@{miInt};NSNumber*miNumeroSuma=@{2+3};NSNumber*miNumeroBooleano=@YES;Sin embargo, al contrario que las cadenas literales que se compilan como constantes en el ejecutable, estos literales se compilan como código equivalente a las llamadas a métodos mencionadas arriba. En particular, bajo manejo manual del conteo de referencia de memoria, estos objetos son autoliberados, lo que requiere especial cuidado cuando por ejemplo son usados con variables de funciones estáticas u otros tipos de variables globales.
Cuando se usa el compilador de AppleLLVM 4.0 o superior, vectores y diccionarios (las clasesNSArray yNSDictionary) pueden ser manipuladas usando subíndices.[15] Los subíndices se pueden usar para recuperar valores de índices (vectores) o llaves (diccionarios) y con objetos mutables también puede user para fijar objetos a índices o llaves. En el código, los subíndices son representados usando corchetes[ ].[16]
Ejemplos sin subíndices:
idobjeto1=[unVectorobjectAtIndex:0];idobjeto2=[unDiccionarioobjectForKey:@"llave"];[unVectorMutablereplaceObjectAtIndex:0withObject:objeto3];[unDiccionarioMutablesetObject:objeto4forKey:@"llave"];
Ejemplos con subíndices:
idobjeto1=unVector[0];idobjeto2=unDiccionario[@"llave"];unVectorMutable[0]=objeto3;unDiccionarioMutable[@"llave"]=objeto4;
Sintaxis de Objective-C "Moderna" (1997)
[editar]Tras la compra de NeXT por parte de Apple, se hicieron varios intentos para asemejar más el lenguaje con respecto a otros lenguajes existentes. Uno de estos intentos fue la introducción de lo que se denominó en su momento "Sintaxis moderna" para Objective-C (en oposición a la existente, sintaxis "clásica"). No había cambios en el comportamiento real, simplemente era una sintaxis alternativa.La invocación a un método se hacía de este modo:
objeto=(MiClase.alloc).init;objeto.primeraEtiq(param1,param2);
Y pasó a escribirse de este otro modo:
objeto=[[MiClasealloc]init];[objetoprimeraEtiq:param1segundaEtiq:param2];
Similarmente, las declaraciones pasaron de ser así:
-(void)primeraEtiq(intparam1,intparam2);
a ser así:
-(void)primeraEtiq:(int)param1segundaEtiq:(int)param2;
Esta sintaxis "moderna" no está soportada en dialectos actuales de Objective-C.
Portable Object Compiler
[editar]Además de las implementaciones deGCC/NeXT/Apple, que añadieron varias extensiones a la implementación original de Stepstone, también existe otra implementaciónlibre y abierta de Objective-C llamada Protable Object Compiler.[17] El conjunto de extensiones implementadas por el Portable Object Compiler difiere de las implementaciones GCC/NeXT/Apple; en particular, incluye blocks similares a los deSmalltalk para Objective-C, mientras que carece de protocolos y categorías, dos características usadas ampliamente en OpenStep y sus derivados. En conjunto, POC representa una etapa vieja, pre-NeXT, de la evolución del lenguaje, simplemente conforme al libro de 1991 de Brad Cox.
También incluye una librería de tiempo de ejecución llamada ObjectPak, que está basada en la librería original ICPak101 de Cox (que a su vez deriva de la librería de clases Smalltalk-80) y es radicalmente diferente a la de OneStep FoundationKit.
El sistema PC GEOS usaba un lenguaje de programación conocido comoGEOS Objective-C ogoc;[18] a pesar de su similar nombre, los dos lenguajes son similares en un concepto global y por el uso de palabras clave precedidas por el signo @.
La suite de compiladoresClang, parte del proyectoLLVM, implementa Objective-C así como otros lenguajes.