Conformità a più protocolli

31 maggio 2017

Diversamente dal concetto di ereditarietà, che in Objective-C è singola e quindi impedisce a una classe di estendere più di una classe, non esistono vincoli relativi al numero di protocolli a cui una classe può essere conforme.

Immaginiamo un protocollo DriverelessVehicleProtocol, e facendo riferimento alla classe Car della lezione precedente, vediamo come renderla conforme anche a questo nuovo protocollo:

#import <Foundation/Foundation.h>
#import "VehicleProtocol.h"

@interface Car : NSObject<VehicleProtocol, DriverelessProtocol>

@end

Ovviamente dovremo anche implementare in Car.m gli eventuali metodi dichiarati da DriverelessProtocol.

Metodi opzionali

Con Objective-C possiamo anche dichiarare dei metodi opzionali, ovvero dei metodi che non devono necessariamente essere implementati dalla classe conforme al protocollo.

Esaminiamo il seguente esempio:

#import <Foundation/Foundation.h>

@protocol VehicleProtocol <NSObject>

- (int)numberOfWheels;

@optional
- (int)availableFuel;

@end

Abbiamo aggiunto la definizione del metodo availableFuel, che però è opzionale. Ciò significa che potremo implementarlo, ad esempio, nella classe Car e non nella classe Bicycle (facendo ancora riferimento agli esempi della lezione precedente).

Apriamo il file Car.m e modifichiamolo come segue:

#import "Car.h"

@implementation Car

-(int) numberOfWheels {
    return 4;
}

-(int) availableFuel {
    return 30;
}

@end

Se compiliamo, non ci sarà restituito alcun errore, anche se Bicycle non possiede questo nuovo metodo.

Torniamo ora al file main.m, modificandolo come segue:

@import Foundation;

#import "Car.h"
#import "Bicycle.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        id<VehicleProtocol> vehicle = [Car new];
        NSLog(@"%d", [vehicle availableFuel]);
    }
    return 0;
}

Premendo CMD + R per eseguire il progetto, vedremo nella console di debug che verrà stampato il numero 30.

Tuttavia, se inseriamo una Bicycle all’interno della variabile vehicle:

@import Foundation;

#import "Car.h"
#import "Bicycle.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        id<VehicleProtocol> vehicle = [Bicycle new];
        NSLog(@"%d", [vehicle availableFuel]);
    }
    return 0;
}

otterremo un errore di runtime:

 -[Bicycle availableFuel]: unrecognized selector sent to instance 0x100304620

Il compilatore ci sta dicendo che non ha trovato il metodo availableFuel dentro Bicycle. Per scrivere codice robusto nel caso di metodi opzionali, in genere è bene effettuare un check prima di invocare un metodo opzionale, come mostrato di seguito.

@import Foundation;

#import "Car.h"
#import "Bicycle.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        id<VehicleProtocol> vehicle = [Bicycle new];
        
        if ([vehicle respondsToSelector:@selector(availableFuel)]) {
            NSLog(@"%d", [vehicle availableFuel]);
        }
    }
    return 0;
}

In questo modo, invocando [vehicle respondsToSelector:@selector(availableFuel)], ci stiamo assicurando che il metodo availableFuel sia stato effettivamente implementato.

Tutte le lezioni

1 ... 13 14 15 ... 21

Se vuoi aggiornamenti su Conformità a più protocolli inserisci la tua e-mail nel box qui sotto:
Tags:
 
X
Se vuoi aggiornamenti su Conformità a più protocolli

inserisci la tua e-mail nel box qui sotto:

Ho letto e acconsento l'informativa sulla privacy

Acconsento al trattamento di cui al punto 3 dell'informativa sulla privacy