iOS para desarrolladores .NET: herencia y protocolos

jueves, 12 de febrero de 2015


Una vez que ya hemos visto como se definen las clases en Objetive-C en anteriores artículos, en este artículo vamos a ver de que forma podemos realizar herencia y abstraer clases mediante protocolos, que es un concepto similar a interfaces en C#.

Herencia

En Objetive C al igual que en C# podemos realizar herencia simple, vamos a poder crear una clase que herede de otra y así poder reutilizar código. Todos los objetos como mínimo heredan de NSObject.

C#

En C# para indicar que heredamos de una clase se realiza poniendo dos puntos despues del nombre de clase y a continuación la clase base de la que se hereda.

public class Person 
{

}

public class Employee: Person 
{

}


Si la clase base tiene un constructor con parámetros cuando creamos un objeto de la clase derivada, esta debe invocarlo desde su constructor.

public class Person 
{
    public string FirstName {get; private set;}
    public string LastNameName {get; private set;}

    public Person (string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }
}

public class Employee: Person 
{
    public double Salary {get; private set;}

    public Person (string firstName, string lastName,double salary):base(firstName, lastName)
    {
        Salary = salary;
    }
}

Objetive-C

En Objetive-C para indicar que heredamos de una clase base se realiza en el fichero de cabecera, se ponen dos puntos y el nombre de la clase base a continuación del nombre de la clase derivada.

XURPerson.h

@interface XURPerson:NSObject

@end

XURPerson.m

@implementation XURPerson

@end

XUREmployee.h

@interface XUREmployee:XURPerson

@end

XUREmployee.m

@implementation XUREmployee

@end


En objetive C recordad que no tenemos constructores si no inicializadores, y además los inicializadores se heredan por lo tanto si defino un constructor en la clase base, puedo utilizarlo para crear una instancia de la clase derivada.

Siguiendo el mismo ejemplo que hemos visto para C#, en Objetive C tenemos que invocar el inicializador designado de la clase base desde el inicializador designado de la clase derivada mediante la palabra clave super.

//XURPerson.h

@interface XURPerson:NSObject

@property (strong,nonatomic,readonly) NSString *fisrtName;
@property (strong,nonatomic,readonly) NSString *lastName;

-(instancetype) initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName;
@end

//XURPerson.m

@implementation XURPerson

-(instancetype) initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName{
    self = [super init];

    if (self) {
        _fisrtName = fisrtName;
        _lastName = lastName;
    }
    return self;
}
@end

//XUREmployee.h

@interface XUREmployee:XURPerson

@property (nonatomic,readonly) double salary;

-(instancetype) initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName salary:(double)salary;
@end

//XUREmployee.m

@implementation XUREmployee
-(instancetype) initWithFirstName:(NSString *)firstName lastName:(NSString *)lastName salary:(double)salary{
    self = [super initWithFirstName:firstName lastName:lastName];

    if (self) {
        _salary = salary;
    }
    return self;
}
@end

Protocolos

Así como en C# o Java tenemos interfaces como mecanismo de abstracción y de contrato que deben cumplir las clases que lo implementan, en Objetive-C el concepto que tenemos para el mismo objetivo son los protocolos.

C#

En C# se define un interface solo con la firma del método y en la clase se indica que una clase implementa un interface en el mismo lugar donde podemos indicar la clase de la que se hereda. Si se hereda de una clase y se implementa un interfacea la vez, primero se pone la clase base y luego el interface separado por una coma.

public interface IEntity
{

}

public class Person 
{

}

public class Employee: Person , IEntity
{

}

Objetive-C

En Objetive-C se definen los protocolos solo con la firma como con las cabeceras y se definen en un fichero .h, y hay que indicar que cumple el protocolo NSObject, aparte de tener NSObject como la clase más básica de la que hay que heredar, también existe un protocolo NSObject. Para indicar que una clase cumple un protocolo se pone entre corchetes angulares.

//XUREntity
@protocol XUREntity<NSObject>{
    
}

//XURPerson.h

@interface XURPerson:NSObject

@end

//XURPerson.m

@implementation XURPerson

@end

//XUREmployee.h

@interface XUREmployee:XURPerson<XUREntity>

@end

//XUREmployee.m

@implementation XUREmployee

@end


Como principal diferencia entre interfaces de C# y protocolos de Objetive C, es que por defecto todo lo que se define en el protocolo es obligatorio pero podemos indicar mediante @optional métodos que son opcionales y no es obligatorio implementarlos. Si ponemos @optional todos los métodos hasta el final del protocolo o hasta un @required van a ser opcionales.

@protocol MyProtocol

- (void)requiredMethod;

@optional
- (void)anOptionalMethod;
- (void)anotherOptionalMethod;

@required
- (void)anotherRequiredMethod;

@end


En tiempo de compilación podemos verificar si la clase implementa un método y deberiamos utilizarlo para los métodos que el protocolo indica que son opcionales.

NSString *thisSegmentTitle;

if ([self.dataSource respondsToSelector:@selector(titleForSegmentAtIndex:)]) {
    thisSegmentTitle = [self.dataSource titleForSegmentAtIndex:index];
}

Resumen

En este artículos hemos comparado como se realiza en C# y ObjetiveC dos de los pilares funcamentales de la programación orientada a objetos como son la herencia y como definir un contrato que la clase debe cumplir, esta abstracción en C# se consigue con interfaces y en Objetive-C con protocolos. La idea es parecida pero tienen alguna diferencia como lo que hemos visto que en los protocolos se pueden definir métodos opcionales.

Libros relacionados

iOS Programming for .Net Developers

iOS Programming: The Big Nerd Ranch Guide

Objective-C Programming: The Big Nerd Ranch Guide

No hay comentarios:

Publicar un comentario