martes, 30 de agosto de 2011

Herencia y clases abstractas en Objective C

¿Qué es la herencia?

Supongamos que queremos tener un array al que llamaremos "Zoologico". Y que este array sólo puede contener "Animales".

Ahora supongamos que queremos implementar un mono, un elefante y un pájaro, como clases. Todos ellos son animales, por tanto, tienen propiedades comunes a todos los animales, pero cada animal, tiene sus "diferencias". Por ejemplo, el pájaro tiene alas, y el mono no. O el elefante tiene trompa, y el pájaro un pico. Imaginaos que queremos tener una representación gráfica distinta para cada animal, por tanto debemos crear una clase Animal, del tipo CCSprite.

@interface Animal: CCSprite {
    int numeroDePatas;
    bool tienePlumas;
    bool tienePelo;
    bool tienePico;
    bool tieneTrompa;
    bool tieneAlas;
}
-(void) saluda;
@protocol Especializacion
-(void) desplazate;
@end



@implementation Animal
-(id) init
{
    if( (self=[super init])) {
    }
    return self;
}

-(void) saluda{
    NSLog(@"%@",@"Soy un animal");
}

-(void) dealloc{
    [super dealloc];
}

A grandes rasgos, hemos creado un animal (a falta de poner otras muchas caracteristicas). La cual tiene informacion general sobre un animal.

Ahora queremos implementar, una clase Mono, que herede de Animal.

@interface Mono : Animal Especializacion{
    // Aquí pondríamos variables que nos interesen
}
-(void) cuelgaDeArboles;
@end

Y en el módulo de la clase, deberemos implementar los procedimientos de "Protocol" y si queremos, "sobreescribir" los métodos de la clase Animal, desde una clase hijo.

@implementation Mono
-(id) init
{
    if( (self=[super init])) {
        //Cargo la imagen del mono
        numeroDePatas = 4;
        tienePlumas = false;
        tienePelo = true;
        tienePico = false;
        tieneTrompa = false;
        tieneAlas = false;
    }
    return self;
}

-(void) saluda{ //He sobreescrito el método saluda de Animal.
    NSLog(@"%@",@"¡Soy un mono!");
}

-(void) dealloc{
    [super dealloc];
}

-(void) desplazate{
    //Me desplazo como un mono
}

-(void) cuelgaDeArboles{
    //Bla bla bla...
}

Ahora voy a implementar lo que sería un elefante.

@interface Elefante : Animal Especializacion{
    // Aquí pondríamos variables que nos interesen
}
@end

Y en el módulo de la clase, deberemos implementar los procedimientos de "Protocol" y si queremos, "sobreescribir" los métodos de la clase Animal, desde una clase hijo.

@implementation Elefante
-(id) init
{
    if( (self=[super init])) {
        //Cargo la imagen del elefante
        numeroDePatas = 4;
        tienePlumas = false;
        tienePelo = false;
        tienePico = false;
        tieneTrompa = true;
        tieneAlas = false;
    }
    return self;
}

-(void) dealloc{
    [super dealloc];
}

-(void) desplazate{
    //Me desplazo como un elefante
}


Si observas, el método Saluda de Animal, ha sido reemplazado por el método saluda de Mono, pero no en la clase elefante. ¿Que significa eso?

Mono *mono = [[Mono alloc] init];
Elefante* elefante = [[Elefante alloc] init];

[elefante saluda]; //La salida en pantalla será, "Soy un animal"
[mono saluda];     //La salida en pantalla será, "¡Soy un mono!"

¿Qué tiene esto de bueno? Pues que por ejemplo, si tuvieramos alguna restricción de tipos a la hora de guardar un elemento en un array, y no pudieramos guardar clases de distinto tipo en el array... Pues esto sería solución. Ya que la clase "padre" de todo mono, elefante, o pájaro, es "Animal". Por lo que el array que tuviesemos que definir, lo definiriamos para "Animal".

PD: Cada vez que he escrito Especializacion en @implementation, va entre <>.

1 comentario:

  1. puedo utilizar los valores de una variable de una clase en otra clase??

    ResponderEliminar