Articoli con Tag ‘Object-Oriented’

Objective-C: esporre proprietà in una classe

Vorrei mostrare e discutere alcuni esempi sul come aggiungere e manipolare proprietà in una Classe Objective-C. Un esempio classico, per l’appunto, è il seguente; nella definizione della nostra interfaccia di classe definiamo due proprietà nome e cognome:

1
2
3
4
5
6
7
8
9
10
11
// MyClass.h
#import <Foundation/Foundation.h>

@interface MyClass : NSObject {
    NSString *nome;
    NSString *cognome;
}

@property (retain) NSString *nome;
@property (retain) NSString *cognome;
@end

Nel file di implementazione inseriamo la dichiarazione @synthesize in modo tale che Xcode produca per noi i metodi getter e setter usati rispettivamente per leggere ed impostare le nostre due proprietà:

1
2
3
4
5
6
7
8
// MyClass.m
#import "MyClass.h"

@implementation MyClass

@synthesize nome, cognome;

@end

Quando andremo ad utilizzare la nostra classe MyClass, cioè quando istanziaremo un oggetto di tipo MyClass, possiamo scrive:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// qualsiasi altra classe, come AppDelegate
// nel file .h
#import <UIKit/UIKit.h>
#import "MyClass.h"

@class TestViewController;

@interface TesAppDelegate : NSObject <UIApplicationDelegate> {
    UIWindow *window;
    TestViewController *viewController;

    MyClass *miaClasse;
}

// nel file .m
miaClasse = [MyClass alloc];
miaClasse.nome = @"Giovambattista";
NSLog(@"miaClasse.nome = %@", miaClasse.nome);

Oppure, che è equivalente:

1
2
3
// sempre nel file .m
[miaClasse setNome:@"Undolog"];
NSLog(@"miaClasse.nome = %@",[miaClasse nome]);

Fin qui tutto bene. Tuttavia potrebbe fuorviare l’equivalenza delle “variabli” interne (ivar) con il nome della proprietà vera e propria. Per capire la differenza, ripropongo lo stesso esempio facendo a meno, questa volta, di @synthesize. Ora, quindi, dovremmo occuparci noi di scrivere i metodi getter e setter. Per sottolineare ulteriormente le differenze, rinominerò le variabili interne inserendo un underscore davanti al nome. Ma vediamo il codice:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#import <Foundation/Foundation.h>

@interface MyClass : NSObject {
    NSString *_nome;
    NSString *_cognome;
}

- (NSString *) nome;                               // get
- (NSString *) cognome;                            // get

- (void) setNome: (NSString *)stringaIngresso;     // set
- (void) setCognome: (NSString *)stringaIngresso;  // set

@end

A differenza dell’esempio precedente i puntatori alla variabili interne (incapsultate) sono diventati _nome e _cognome. Inoltre troviamo quattro definizioni di metodi che rappresentano le nostre get e set. @property è scomparso, in quanto non serve più.
Vediamo il file di implementazione MyClass.m:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#import "MyClass.h"

@implementation MyClass

// get per "nome"
- (NSString *) nome {
    return _nome;
}
// set per "nome"
- (void) setNome: (NSString *)stringaIngresso {
    _nome = stringaIngresso;
}

// get per "cognome"
- (NSString *) cognome {
    return _cognome;
}
// set per "cognome"
- (void) setCognome: (NSString *)stringaIngresso {
    _cognome = stringaIngresso;
}

@end

Una classe così scritta potrà essere utilizzata esattamente come la precedente, cioè:

1
2
3
4
5
6
7
8
miaClasse = [MyClass alloc];
miaClasse.nome = @"Giovambattista";
NSLog(@"miaClasse.nome = %@", miaClasse.nome);

// Oppure, che è equivalente:

[miaClasse setNome:@"Undolog"];
NSLog(@"miaClasse.nome = %@",[miaClasse nome]);

A livello didattico l’abbandono di @synthesize ci ha costretto a scrivere “da soli” i metodi di get e set, evidenziando – anche con l’aggiunta dell’underscore – le differenze tra il nome della proprietà e la sua ivar interna _nome.
A livello funzionale l’uso dei metodi personali get e set permette un reale controllo del dato prima della sua impostazione (o prima della sua lettura) e quindi un reale incapsulamento per proteggere la variabile interna.
Ad esempio sarebbe possibile impedire il passaggio di stringhe vuote alla proprietà nome:

1
2
3
4
- (void) setNome: (NSString *)stringaIngresso {
    if( stringaIngresso == @"" ) stringaIngresso = @"senza nome";
    _nome = stringaIngresso;
}

Ulteriore variante

Se desiderate utilizzare le variabili interne con l’underscore davanti (chi rpoviene da Adobe Actionscript potrebbe essere abituato così) non è necessario abbandonare l’uso della direttiva @synthesize. Xcode permette infatti di “fondere” i metodi sopra indicati:

1
2
@synthesize nome = _nome;
@synthesize cognome = _cognome;

Così facendo potremmo usare internamente il puntatore a _nome, “sintetizzato” – verso l’esterno – come proprietà nome. Inoltre, se è vero che l’uso di @synthesize produce la generazione automatica dei metodi (messaggi) di getter e setter, è vero anche che lo fa solo se non li trova, quindi se desiderate “implementare” un vostro metodo di getter e/o setter potete farlo anche se avete usato la direttiva @synthesize.

Allocazioni di memoria

Negli esempi di sopra ho omesso alcuni dettagli importanti ai fini di una reale implementazione. Prima di tutto non ho illustrato nessun metodo init(), utile ai fini dell’inizializzazione dell’oggetto e dei sui valori di default. Inoltre, manca l’aggiunta di un metodo dealloc():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// file MyClass.m
#import "MyClass.h"

@implementation MyClass

- (id) init {
    if ( self = [super init] ) {
        _nome = @"Nome preimpostato";
        _cognome = @"Cognome preimpostato";
    }
    return self;
}

- (void) dealloc {
    [_nome release];
    [_cognome release];
    [super dealloc];
}

- (NSString *) nome {
    return _nome;
}
- (void) setNome: (NSString *)stringaIngresso {
    if( stringaIngresso == @"" ) stringaIngresso = @"senza nome";
    _nome = stringaIngresso;
}

- (NSString *) cognome {
    return _cognome;
}
- (void) setCognome: (NSString *)stringaIngresso {
    _cognome = stringaIngresso;
}

@end

In futuro vedremo poi i dettagli sulle proprietà readonly, retain, etc… :)

Continua...

Da Actionscript ad Objective-C

Ho pensato che potrebbe essere utile a chi si è avvicinato da poco allo sviluppo di applicazioni per Apple iPhone, confrontare Adobe Actionscript – il linguaggio utilizzato in Adobe Flash e Adobe Flex, più diffuso tra i neo-programmatori – e Objective-C, il linguaggio utilizzato da Apple per sviluppare le sue applicazioni. Objective-C è a tutti gli effetti un linguaggio ad oggetti nel senso puro, non che Actionscript non lo sia, ma Objective-C ha sicuramente una marcia in più in quanto è un’estensione dell’ANSI C e la sua sintassi è un mix tra C/C++ e Smalltalk; è un vero OO (Object-oriented language).

Continua...

Overloading

L’overloading è una caratteristica davvero utile di alcuni linguaggi di programmazione ad oggetti. Tuttavia non tuti i linguaggi OO la supportano, e alcuni la “implementano” in modo o limitato o differente. In linea generale, per le funzioni o metodi, l’overloading permette di creare due o più funzioni/metodi che hanno lo stesso nome ma accettano parametri differenti, ad esempio:

Continua...

Linguaggi di sviluppo

Ho “riesumato” questo mio articolo scritto un po’ di anni fa. L’ho leggermente rivisto, aggiornando qualcosina qua e là, tuttavia credo sia ancora attuale ed interessante.

INTRODUZIONE

Che cos’è un linguaggio di sviluppo? Un elaboratore elettronico, alias PC (Personal Computer), ha un suo linguaggio personale. Questo linguaggio viene chiamato codice macchina, per intendere che ogni macchina, quindi ogni elaboratore (PC Compatibili, Apple, Unix, ecc…), ne ha uno esclusivo e proprietario. I programmi che vediamo “girare” sul nostro PC vengono principalmente eseguiti da quel misterioso oggetto chiamato microprocessore. Questo rappresenta il cuore, l’unità intelligente, di ogni elaboratore elettronico. In realtà una applicazione non viene eseguita solo dal microprocessore ma si appoggia, per così dire, a quello che viene chiamato sistema operativo: uno strato software fornito dal produttore della macchina (si veda, ad esempio, i Macintosh della Apple).

Continua...

Classi, Oggetti e Istanze

Ho notato spesso confusione quando si parla di Classi, Oggetti ed Istanze. Chi non è particolarmente istruito sulla programmazione ad oggetti spesso confonde il vero significato di questi termini. Sapevo, tuttavia, che esistono due scuole di pensiero riguardo alla definizione di Classe e Oggetto. A me piace la “scuola” che indica la Classe come definizione di un possibile Oggetto e, quindi, l’Oggetto come Istanza della Classe.

Sembra banale, tuttavia mi è capitato – discorrendo con altri – di trovarmi in “conflitto” (per così dire) e poi cadere in equivoci, quando si usano questi termini, partendo casomai dal presupposto che “l’altro” li intenda esattamente come noi.

Io la vedo in questo modo; una Classe è una definizione! Viene appunto definita una classe di possibili oggetti. La Classe è l’insieme di metodi e proprietà (se volete possiamo aggiungere anche gli eventi – che altro non solo che speciali metodi…) che possiederà l’oggetto.

Ad esempio quando scriviamo in Actionscript, o qualsiasi altro linguaggio ad oggetti:

1
2
3
4
class MiaClasse {
    function MiaClass() {}
    function MioMetodo() {}
}

Abbiamo definito una Classe e non un Oggetto. Al limite abbiamo “definito” un “possibile” oggetto. Potremmo addirittura sostenere, e non a torto, che l’Oggetto esiste a runtime mentre la Classe no (in verità esistono Classi dinamiche che possono essere definite – e poi usate per creare oggetti – anche a runtime). Escludo le classi statiche, ovviamente che – alla fine – altro non sono che sotto-istanze (o istanze nascoste) e quindi oggetti veri e propri.

Quando invece abbiamo:

1
var mioOggetto:MiaClasse = new MiaClasse();

Ecco che mioOggetto è una istanza di MiaClasse()! Cioè mioOggetto è un Oggetto – appunto – di tipo MiaClasse().

Ne deriva, proprio nella filosofia ad oggetti, che di Oggetti di tipo MiaClasse() ne posso avere quanti ne voglio, cosa che non può essere – per la definizione stessa – di MiaClasse(). Ad esempio, se vale ed ha senso la relazione:

1
2
3
4
5
var mioOggetto_1:MiaClasse = new MiaClasse();
var mioOggetto_2:MiaClasse = new MiaClasse();
var mioOggetto_3:MiaClasse = new MiaClasse();
...
var mioOggetto_n:MiaClasse = new MiaClasse();

Non ha significato:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MiaClasse {
    function MiaClass() {}
    function MioMetodo_2() {}
}

class MiaClasse {
    function MiaClass() {}
    function MioMetodo_2() {}
}

class MiaClasse {
    function MiaClass() {}
    function MioMetodo_3() {}
}

Istanza e Oggetto, quindi, coincidono e sono usate alternativamente per lo stesso significato in diversi contesti.

Probabilmente non frega molto a nessuno… questione di esigenze di completezza… :)

Continua...

Scrivere buon codice OO in Adobe Flash

Ecco alcuni consigli su come scrivere un buon codice Object Oriented (OO) in Adobe Flash, soprattutto per chi ancora usa la versione MX in attesa di passare alla CS3.

Organizzare le cartelle delle classi

Prima di tutto l’organizzazione delle classi rende il lavoro di manutenzione del codice estremamente più semplice. Inoltre è possibile creare una vera e propria libreria personale da poter riutilizzare in altri progetti. Flash usa una nomenclatura legata al filesystem, quindi l’organizzazione in cartelle si rifletterà anche sull’importazione delle classi. Se ad esempio creiamo la sequenza di cartelle “mylibrary/grafica/plot” e inseriamo una nostra classe ActionScript “PlotClass.as”, quando andremo ad importare la classe dovremmo usare:

1
import mylibrary.grafica.plot.PlotClass;

Se la libreria (cartella) “mylibrary” non si trova nella cartella del nostro filmato o progetto, usare l’impostazioni di pubblicazione di Flash per selezionare il percorso:

Impostazione percoroso librerie

Continua...


Stop SOPA