Creando una clase abstracta en Objective-C

Resuelto Jonathan Arbogast asked hace 15 años • 22 respuestas

Originalmente soy un programador de Java que ahora trabaja con Objective-C. Me gustaría crear una clase abstracta, pero eso no parece posible en Objective-C. es posible?

Si no, ¿qué tan cerca de una clase abstracta puedo llegar en Objective-C?

Jonathan Arbogast avatar Jun 24 '09 01:06 Jonathan Arbogast
Aceptado

Normalmente, las clases Objective-C son abstractas solo por convención; si el autor documenta una clase como abstracta, simplemente no la use sin subclasificarla. Sin embargo, no existe ninguna aplicación en tiempo de compilación que impida la creación de instancias de una clase abstracta. De hecho, no hay nada que impida que un usuario proporcione implementaciones de métodos abstractos a través de una categoría (es decir, en tiempo de ejecución). Puede obligar a un usuario a al menos anular ciertos métodos generando una excepción en la implementación de esos métodos en su clase abstracta:

[NSException raise:NSInternalInconsistencyException 
            format:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)];

Si su método devuelve un valor, es un poco más fácil de usar

@throw [NSException exceptionWithName:NSInternalInconsistencyException
                               reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)]
                             userInfo:nil];

entonces no es necesario agregar una declaración de devolución del método.

Si la clase abstracta es realmente una interfaz (es decir, no tiene implementaciones de métodos concretos), utilizar un protocolo Objective-C es la opción más apropiada.

Barry Wark avatar Jun 23 '2009 18:06 Barry Wark

No, no hay forma de crear una clase abstracta en Objective-C.

Puede burlarse de una clase abstracta, haciendo que los métodos/selectores llamen a DoesNotRecognizeSelector: y, por lo tanto, generen una excepción que haga que la clase sea inutilizable.

Por ejemplo:

- (id)someMethod:(SomeObject*)blah
{
     [self doesNotRecognizeSelector:_cmd];
     return nil;
}

También puedes hacer esto para init.

Grouchal avatar Jun 23 '2009 18:06 Grouchal

Simplemente retomo la respuesta anterior de @Barry Wark (y actualizo para iOS 4.3) y dejo esto para mi propia referencia:

#define mustOverride() @throw [NSException exceptionWithName:NSInvalidArgumentException reason:[NSString stringWithFormat:@"%s must be overridden in a subclass/category", __PRETTY_FUNCTION__] userInfo:nil]
#define methodNotImplemented() mustOverride()

entonces en tus métodos puedes usar esto

- (void) someMethod {
     mustOverride(); // or methodNotImplemented(), same thing
}



Notas: No estoy seguro de si hacer que una macro parezca una función de C es una buena idea o no, pero lo mantendré hasta que me enseñen lo contrario. Creo que es más correcto usar NSInvalidArgumentException(en lugar de NSInternalInconsistencyException) ya que eso es lo que arroja el sistema de ejecución en respuesta a doesNotRecognizeSelectorser llamado (ver NSObjectdocumentos).

Dan Rosenstark avatar Jun 23 '2011 02:06 Dan Rosenstark

La solución que se me ocurrió es:

  1. Crea un protocolo para todo lo que quieras en tu clase "abstracta"
  2. Cree una clase base (o tal vez llámela abstracta) que implemente el protocolo. Para todos los métodos que desee "abstractos", impleméntelos en el archivo .m, pero no en el archivo .h.
  3. Haga que su clase secundaria herede de la clase base E implemente el protocolo.

De esta manera, el compilador le dará una advertencia para cualquier método en el protocolo que no esté implementado por su clase secundaria.

No es tan conciso como en Java, pero aparece la advertencia del compilador deseada.

redfood avatar Jun 21 '2012 19:06 redfood