2011-09-14 8 views
36

¿Cuál es la diferencia entreEnum formas definitorias en Objective-C

typedef enum { 
    ... 
} Name; 

y

enum { 
    ... 
}; 
typedef NSUInteger Name; 

? Si la funcionalidad es la misma, ¿para qué sirve la segunda forma? ¿No es innecesariamente desordenado?

+1

el segundo deriva un tipo de NSUInteger, no el primero. –

Respuesta

84

enum es tan antiguo como C, por lo tanto, una parte de Objective-C. Es solo una codificación explícita de tipo int. Es bastante útil para la depuración y la mayoría de los compiladores más nuevos pueden realizar optimizaciones basadas en él. (Lo cual debes ignorar por completo). Es más útil para hacer que tu código sea más legible (para cualquier otra persona o para ti después de que hayas dormido).

typedef enum { 
    ... 
} NameType ; 

sería seguido por

NameType name; 

y eso es por lo general el estilo preferido de un typedef,

su segundo ejemplo no atar el typedef a los valores que desee para especificar deberían solo ser del tipo dado.

Tenga en cuenta que esto no le impide ejecutar

name = 10244; // some non-valid value not listed in the enumeration 

pero algunos compiladores podría generar una advertencia en ese caso,


me encontré con uso de Apple de la siguiente hoy:

enum { 
NSFetchedResultsChangeInsert = 1, 
NSFetchedResultsChangeDelete = 2, 
NSFetchedResultsChangeMove = 3, 
NSFetchedResultsChangeUpdate = 4 
}; 
typedef NSUInteger NSFetchedResultsChangeType; 

Lo hacen porque realmente quiere que el NSFetchedResultsChangeType sea del tipo que han definido como NSUInteger.Este puede ser un int pero también puede ser otra cosa. Y con valores de 1, 2, 3 y 4, es algo irrelevante para us de qué tipo es. Pero están codificando a un nivel diferente de abstracción porque son un proveedor de herramientas.

Nunca debe mirar a Apple para codificar sugerencias de estilo. Si ve algo que parece que es una forma más limpia/mejor de codificar, generalmente lo es. Como Kevin mencionó, la estabilidad de API es de suma importancia para ellos.


Edición (Enero 2013) Si usted tiene acceso a los WWDC 2012 Sesión Vídeos, debe ver la Session 405 - Modern Objective-C 6: 00-10: 00. Se debate una nueva sintaxis en el compilador más nuevo que permite el tamaño explícito de un tipo y la vinculación estrecha de los valores a los tipos. (tomado de C++ 11)

enum NSFetchedResultsChangeType : NSUInteger { 
NSFetchedResultsChangeInsert = 1, 
NSFetchedResultsChangeDelete = 2, 
NSFetchedResultsChangeMove = 3, 
NSFetchedResultsChangeUpdate = 4 
}; 
+0

Estoy trabajando en la creación de mi propia biblioteca de funciones para iOS ahora con la intención de venderlas. Supongo, entonces, que debo ir en contra de su comentario en negrita y seguir el estilo de Apple? – ArtOfWarfare

+0

@ArtOfWarfare dependiendo de la amplitud de su objetivo, la respuesta puede variar. Si también se dirigirá a entornos que no sean de Apple, sus archivos de encabezado pueden incluir todo tipo de ofuscación sintáctica. Si solo está apuntando a Apple, mi opinión sería no seguir el ejemplo de Apple, es la planificación a largo plazo. Lo único que ganaría es soporte en una arquitectura hipotética que actualmente nadie prevé. Otros ciertamente estarán en desacuerdo conmigo. (aparte: Apple a menudo se basará en arquitecturas de investigación, otra razón de su agnosticismo arquitectónico). – bshirley

+0

¡Gracias por la nota WWDC! –

9

El primero define un nombre de tipo para hacer referencia a una enumeración. Esta es la forma en que la mayoría de las enumeraciones se nombran en C. Sin embargo, este último es un poco diferente, y prevalece en los marcos de Cocoa. Hay dos razones para usar esto último. El primero es si su enumeración define un campo de bits, y lo querría aquí, porque cuando proporcione un valor de "Nombre" proporcionará una combinación de los valores enum. En otras palabras, si usted dice algo así como

[self doSomethingWithBitfield:(Enum1 | Enum2)] 

usted no está pasando un valor de nombre, sino más bien un entero que es una combinación de los dos.

Sin embargo, las estructuras de Cocoa utilizan esta expresión incluso para valores que no son de bitfield, por una muy buena razón: estabilidad de la API. De acuerdo con el estándar C, el tipo integral subyacente de una enumeración requiere poder contener todos los valores en la enumeración, pero el compilador lo elige de otro modo. Esto significa que agregar un nuevo valor enum podría cambiar el tipo integral de la enumeración (por ejemplo, agregar -1 puede hacerlo firmado, agregar 6 mil millones puede hacer que sea de larga duración, etc.). Esto es algo malo desde el punto de vista de la estabilidad API, porque la codificación de tipo de los métodos que toman los valores de esta enumeración podría cambiar inesperadamente y potencialmente romper código y binarios existentes. Para evitar esto, los marcos de trabajo de Cocoa generalmente definen el tipo como un NSUInteger (o NSInteger si necesitan números negativos), por lo que la API y las codificaciones de tipo se mantienen estables.