objective-c - objc - programa objective c
¿Hay algo así como una lista genérica en Cocoa/Objective-C? (4)
Lo que realmente me gusta en C # son listas genéricas. Una lista que puede contener solo un tipo de objetos. ¿Hay algo así como una lista genérica en Cocoa / Objective-C? Hasta ahora solo conozco a NSArray
quien tomará un puntero a cualquier objeto.
Los NSArrays genéricos se pueden realizar mediante la subclasificación de NSArray
y la redefinición de todos los métodos proporcionados con los más restrictivos. Por ejemplo,
- (id)objectAtIndex:(NSUInteger)index
tendría que ser redefinido en
@interface NSStringArray : NSArray
como
- (NSString *)objectAtIndex:(NSUInteger)index
para que un NSArray contenga solo NSStrings.
La subclase creada se puede utilizar como un reemplazo directo y trae muchas funciones útiles: advertencias del compilador, acceso a la propiedad, mejor creación de código y -completado en Xcode. Todas estas son características de tiempo de compilación, no hay necesidad de redefinir la implementación real. Los métodos de NSArray aún se pueden usar.
Es posible automatizar esto y reducirlo a solo dos declaraciones, lo que lo acerca a los lenguajes que admiten genéricos. WMGenericCollection una automatización con WMGenericCollection , donde las plantillas se proporcionan como Macros de preprocesador C.
Después de importar el archivo de cabecera que contiene la macro, puede crear un NSArray genérico con dos instrucciones: una para la interfaz y otra para la implementación. Solo necesita proporcionar el tipo de datos que desea almacenar y los nombres de sus subclases. WMGenericCollection proporciona tales plantillas para NSArray
, NSDictionary
y NSSet
, así como sus homólogos mutables.
No, Objective-C actualmente no admite el tipado paramétrico para elementos de colección.
Sin embargo, este tema es más complejo de lo que admite la pregunta o las respuestas existentes.
La tipificación paramétrica de colecciones en Objective-C no sería igual a Generics en C # / Java. Por ejemplo, es poco probable que alguna vez vea que Objective-C agrega la capacidad de asegurar que cada objeto agregado a una colección ES un tipo o subtipo NSArray. En cambio, Objective-C podría (y la OMI debería) tener la capacidad de asegurar que cada objeto de una colección CONFORMA a un protocolo / interfaz. (es decir, que implementa un conjunto de métodos requeridos)
¿Por qué?
Objective-C es un lenguaje basado en la compatibilidad del protocolo (interfaz), NO en las relaciones de subtipado. Es decir, los objetos son compatibles si tienen todos los métodos correctos, no miramos ni nos preocupamos por sus tipos reales. De hecho, mirar los tipos reales es una muy mala práctica en Obj-C y muy desalentada. Esta noción a veces se llama "Duck Typing", porque si grazna como un pato, es un pato. No nos importa si literalmente heredó de algún pato específico o no. Esto evita que sea ensillado por otra jerarquía de implementación. - El resultado es que mientras un objeto que sale de la lista tenga un método draw :: funciona, realmente no nos importa si es una subclase de algún objeto específico de JimmyDrawableBase.
Esto no solo hace que el código sea más reutilizable, sino que también alienta un tipo de descomposición del problema ligeramente diferente (¿más funcional?), Ya que no puede confiar en que los objetos se deriven de una clase base dada y tenga una buena cantidad de su clase base. implementación forzada en ellos.
Personalmente, creo que sería bueno para el compilador Obj-C tener una comprobación paramétrica de PROTOCOL * CONFORMANCE *. Es decir, para hacer un NSMutableArray que requiera que todos los objetos colocados en él se ajusten a un protocolo dado (es decir, que tengan un conjunto dado de métodos requeridos).
A veces, incluso esta comprobación de conformidad de protocolo más flexible es resistida por personas de programación dinámica, y con razones de sonido. Los programadores a menudo tienen una manera de especificar en exceso los requisitos de conformidad.
Por ejemplo, es posible que necesite una lista que contenga objetos que se ajusten al protocolo / interfaz NSArray, pero es posible que REALMENTE solo llame a dos de esos métodos. Esto es sobre-conformidad. Alguien que desea insertar un elemento compatible en su matriz se ve obligado a implementar una tonelada de métodos que no está llamando en realidad, al menos todavía (consulte a continuación).
Google Go intenta resolver este problema deduciendo compatibilidad estructural. Es decir, si llama a draw () sobre elementos que salen de una lista, entonces el compilador asegura que todo lo que entra en una lista contiene un método draw (). Si no contiene un método draw (), es un error de compilación colocarlo en la lista. Esto evita que el código simplemente cause el mismo error en el tiempo de ejecución. El problema con esto es que solo funciona para la compilación de todo el programa. Si Google-Go pudiera compilar archivos DLL modulares (que no puede), se encontraría con el problema de que no hay forma de decir que los objetos de la lista deben admitir una interfaz específica de tres métodos, aunque No los llamo hoy, porque podría llamarlos en el futuro .
Entre esas dos soluciones, les gusta el intercambio y la verdad.
Personalmente, me gustaría ver que Objective-C agregue la conformidad del protocolo paramétrico, por lo que podría pedirle al compilador que asegure que el contenido de una colección particular siempre se ajusta a un conjunto dado de protocolos.
También me gustaría que el compilador me ayudara a evitar el exceso de conformidad. Si no estoy llamando a métodos en esos protocolos sobre objetos, debería generar errores / advertencias diciéndome eso. Si quiero mantenerlos en el protocolo a pesar de que no los estoy usando, debería hacer una declaración explícita para cada método en el protocolo que "podría usarse en el futuro, por lo que todos los elementos deben suministrarlo ahora". ". Esto al menos hace que el proceso de exceso de conformidad requiera MÁS trabajo, en lugar de Java / C #, donde requiere menos trabajo.
Objective-C no es compatible con la programación genérica. Siempre puedes usar Objective-C ++ y una lista STL.
Querer esto en una aplicación de Cocoa a menudo es un signo de un diseño débil.
NSArray
es inmutable, por lo que no "tomará un puntero a ningún objeto" y, presumiblemente, ya contiene los objetos correctos cuando se los entregue. Lo que supongo que te preocupa más es un NSMutableArray
en el que piensas que otras partes de tu código podrían agregar el tipo de objeto incorrecto. Pero eche un vistazo al cacao en sí mismo; es increíblemente raro exponer una matriz mutable como parte del diseño de una clase.
En cambio, generalmente expone un NSArray
y un par de métodos para modificar ese conjunto. Algo como:
@class Foo : NSObject
- (NSArray *)bars;
- (void)addBar:(Bar *)bar;
- (void)removeBar:(Bar *)bar;
@end
Esto generalmente detiene la inserción de objetos erróneos simplemente al tener una advertencia de compilación, y luego, por supuesto, puede agregar aserciones dentro de -addBar:
y -removeBar:
si lo desea también.