En Objective-C, las categorías y extensiones son herramientas poderosas que permiten añadir funcionalidades a las clases existentes sin necesidad de modificar su código fuente original. Esto es especialmente útil para mantener el código modular y organizado. En esta sección, aprenderemos cómo utilizar estas características de manera efectiva.

  1. Categorías

1.1 ¿Qué es una Categoría?

Una categoría en Objective-C permite añadir métodos a una clase existente sin necesidad de crear una subclase. Esto es útil para extender la funcionalidad de clases de las que no tenemos el código fuente o para organizar mejor el código.

1.2 Sintaxis de Categorías

Para definir una categoría, se utiliza la siguiente sintaxis:

Archivo de cabecera (.h):

// NSString+ReversedString.h
#import <Foundation/Foundation.h>

@interface NSString (ReversedString)

- (NSString *)reversedString;

@end

Archivo de implementación (.m):

// NSString+ReversedString.m
#import "NSString+ReversedString.h"

@implementation NSString (ReversedString)

- (NSString *)reversedString {
    NSUInteger length = [self length];
    NSMutableString *reversedString = [NSMutableString stringWithCapacity:length];
    
    for (NSInteger i = length - 1; i >= 0; i--) {
        [reversedString appendFormat:@"%C", [self characterAtIndex:i]];
    }
    
    return reversedString;
}

@end

1.3 Uso de Categorías

Una vez definida la categoría, podemos utilizar el nuevo método en cualquier instancia de la clase NSString:

#import "NSString+ReversedString.h"

NSString *originalString = @"Objective-C";
NSString *reversedString = [originalString reversedString];
NSLog(@"Original: %@, Reversed: %@", originalString, reversedString);

1.4 Limitaciones de las Categorías

  • No pueden añadir variables de instancia: Las categorías solo pueden añadir métodos, no pueden añadir propiedades o variables de instancia.
  • Conflictos de nombres: Si dos categorías añaden métodos con el mismo nombre a una clase, puede haber conflictos y comportamiento inesperado.

  1. Extensiones

2.1 ¿Qué es una Extensión?

Una extensión es similar a una categoría, pero se define dentro del archivo de implementación de la clase y se utiliza para añadir métodos privados o para dividir la implementación de una clase en varias partes.

2.2 Sintaxis de Extensiones

Las extensiones se definen de la siguiente manera:

Archivo de cabecera (.h):

// MyClass.h
#import <Foundation/Foundation.h>

@interface MyClass : NSObject

- (void)publicMethod;

@end

Archivo de implementación (.m):

// MyClass.m
#import "MyClass.h"

@interface MyClass ()

- (void)privateMethod;

@end

@implementation MyClass

- (void)publicMethod {
    NSLog(@"Public Method");
    [self privateMethod];
}

- (void)privateMethod {
    NSLog(@"Private Method");
}

@end

2.3 Uso de Extensiones

Las extensiones son útiles para mantener la encapsulación y ocultar detalles de implementación:

MyClass *myObject = [[MyClass alloc] init];
[myObject publicMethod];
// [myObject privateMethod]; // Esto causará un error porque privateMethod no es accesible fuera de la implementación.

  1. Ejercicios Prácticos

Ejercicio 1: Añadir una Categoría

Objetivo: Crear una categoría para la clase NSArray que añada un método para obtener el elemento más frecuente en el array.

Solución:

Archivo de cabecera (.h):

// NSArray+MostFrequentElement.h
#import <Foundation/Foundation.h>

@interface NSArray (MostFrequentElement)

- (id)mostFrequentElement;

@end

Archivo de implementación (.m):

// NSArray+MostFrequentElement.m
#import "NSArray+MostFrequentElement.h"

@implementation NSArray (MostFrequentElement)

- (id)mostFrequentElement {
    NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:self];
    id mostFrequent = nil;
    NSUInteger highestCount = 0;
    
    for (id element in countedSet) {
        NSUInteger count = [countedSet countForObject:element];
        if (count > highestCount) {
            highestCount = count;
            mostFrequent = element;
        }
    }
    
    return mostFrequent;
}

@end

Uso:

#import "NSArray+MostFrequentElement.h"

NSArray *array = @[@1, @2, @3, @1, @2, @1];
id mostFrequent = [array mostFrequentElement];
NSLog(@"Most Frequent Element: %@", mostFrequent);

Ejercicio 2: Añadir una Extensión

Objetivo: Crear una extensión para la clase MyClass que añada un método privado para calcular el cuadrado de un número.

Solución:

Archivo de cabecera (.h):

// MyClass.h
#import <Foundation/Foundation.h>

@interface MyClass : NSObject

- (void)printSquareOfNumber:(NSInteger)number;

@end

Archivo de implementación (.m):

// MyClass.m
#import "MyClass.h"

@interface MyClass ()

- (NSInteger)squareOfNumber:(NSInteger)number;

@end

@implementation MyClass

- (void)printSquareOfNumber:(NSInteger)number {
    NSInteger square = [self squareOfNumber:number];
    NSLog(@"Square of %ld is %ld", (long)number, (long)square);
}

- (NSInteger)squareOfNumber:(NSInteger)number {
    return number * number;
}

@end

Uso:

MyClass *myObject = [[MyClass alloc] init];
[myObject printSquareOfNumber:5];

  1. Resumen

En esta sección, hemos aprendido sobre las categorías y extensiones en Objective-C. Las categorías nos permiten añadir métodos a clases existentes sin modificar su código fuente, mientras que las extensiones nos permiten añadir métodos privados y mantener la encapsulación. Ambas herramientas son esenciales para escribir código modular y organizado en Objective-C.

En el próximo tema, exploraremos los bloques y closures, que son fundamentales para la programación funcional y la gestión de tareas asíncronas en Objective-C.

© Copyright 2024. Todos los derechos reservados