Archivi tag: OOP

Interazione tra oggetti

Dopo la parentesi sugli array (parte 1, parte 2), torniamo a parlare di oggetti. Una domanda che può sorgere spontanea è: possono due oggetti interagire tra loro?

Riprendendo porzioni di codice che già abbiamo usato in precedenza oggi realizzeremo uno sketch in cui sarà presente un’interazione tra due oggetti: cambieremo il colore dello sfondo da nero a rosso quando due cerchi si sovrapporranno uno all’altro.

Analizziamo il problema

Come posso sapere se due cerchi si intersecano? Per crearli in Processing utilizziamo la funzione ellipse() che accetta quattro parametri: posizione x e y del centro più la larghezza e l’altezza. Nel caso in cui questi ultimi due parametri coincidano avrò un cerchio.

Grazie agli studi fatti alle scuole elementari e medie sappiamo che esiste una cosa chiamata raggio che determina la distanza tra il centro e il bordo del cerchio. A questo punto, la soluzione al problema dovrebbe esservi chiara: se la distanza tra il centro del primo cerchio e del secondo è inferiore alla somma dei due raggi, allora i cerchi saranno sovrapposti, altrimenti no.

Se avete dimenticato la geometria, questa immagine dovrebbe esservi d’aiuto per visualizzare quello che ho appena scritto:

Cerchi sovrapposti

Punto di partenza: copia-incolla

Ora che abbiamo individuato il fulcro del nostro programma, faccio copia-incolla del codice dall’esercizio Bouncing Ball, semplificandolo in alcune parti: all’interno della mia classe “Ball” utilizzerò un solo constructor a cui passerò solo il valore relativo al raggio del cerchio. Posizione x e y del centro e velocità di spostamento saranno creati in modo casuale.

Mantengo inalterato il metodo display() mentre modifico leggermente il metodo move() nel quale inserisco anche la parte di codice relativa al controllo sui bordi.

Nel programma principale creo e inizializzo due oggetti di tipo Ball chiamati myBall1 e myBall2 e, all’interno di draw() li visualizzo e li faccio muovere:

class Ball {
  // Variabili
  int radius;
  float ellipseX, ellipseY, speedX, speedY;
  // Constructor
  Ball(int _radius) {
    radius = _radius;
    ellipseX = random(width);
    ellipseY = random(height);
    speedX = random(2, 5);
    speedY = random(2, 5);
  }
  // Metodi
  void display() {
    ellipse(ellipseX, ellipseY, radius, radius);
  }
  
  void move() {
    ellipseX = ellipseX + speedX;
    ellipseY = ellipseY + speedY;
    if (ellipseX > width || ellipseX < 0) {
      speedX = speedX * -1;
    }
    if (ellipseY > height || ellipseY < 0) {
      speedY = speedY * -1;
    }
  }
}
Ball myBall1, myBall2;

void setup() {
  size(700, 500);
  myBall1 = new Ball(100);
  myBall2 = new Ball(50);
}

void draw() {
  background(0);
  myBall1.display();
  myBall2.display();
  myBall1.move();
  myBall2.move();
}

Determinare la sovrapposizione

Ora non mi resta che creare un nuovo metodo all'interno della classe per verificare l'effettiva sovrapposizione dei due cerchi. Il primo passo che potremmo pensare di fare è creare una funzione in cui utilizziamo sei parametri (posizione x, y e raggio dei due cerchi) per verificare l'intersezione dei due cerchi.

Dal momento che utilizziamo gli oggetti, possiamo arrivare a una soluzione più semplice: l'oggetto myBall1 interseca myBall2?

Aggiungiamo un metodo alla nostra classe: il tipo di dato che verrà restituito da questo nuovo metodo sarà di tipo booleano (true in caso di sovrapposizione e false in caso contrario) per cui scriviamo quanto segue:

boolean isOver() {

}

Per calcolare la distanza tra due punti utilizziamo la funzione dist() che accetta quattro parametri e restituisce un dato di tipo float:

dist(x1, y1, x2, y2);

Chiaramente i primi due parametri saranno ellipseX ed ellipseY del cerchio che stiamo prendendo in esame. Ma come facciamo a passare i dati del secondo cerchio? Nel secondo post relativo agli oggetti abbiamo visto come passare dei parametri all'interno del costructor, possiamo usare lo stesso sistema per passare delle variabili anche ai metodi.

La cosa davvero interessante è che anziché passare una variabile, passeremo l'intero oggetto:

boolean isOver(Ball b) {
 float distance = dist(ellipseX, ellipseY, b.ellipseX, b.ellipseY);
 if(distance <= (radius+b.radius)) {
  return true;
 } else {
  return false;
 }
}

Ecco il codice completo della classe Ball:

class Ball {
  
  int radius;
  float ellipseX, ellipseY, speedX, speedY;
  
  Ball(int _radius) {
    radius = _radius;
    ellipseX = random(width);
    ellipseY = random(height);
    speedX = random(2, 5);
    speedY = random(2, 5);
  }
  
  void display() {
    ellipse(ellipseX, ellipseY, radius, radius);
  }
  
  void move() {
    ellipseX = ellipseX + speedX;
    ellipseY = ellipseY + speedY;
    if (ellipseX > width || ellipseX < 0) {
      speedX = speedX * -1;
    }
    if (ellipseY > height || ellipseY < 0) {
      speedY = speedY * -1;
    }
  }
  
  boolean isOver(Ball b) {
    float distance = dist(ellipseX, ellipseY, b.ellipseX, b.ellipseY);
    if(distance <= (radius+b.radius)) {
      return true;
    } else {
      return false;
    }
  }
}

Interazione tra due oggetti

Aggiorniamo il codice dello sketch principale aggiungendo all'interno di draw le seguenti righe di codice:

if(myBall2.isOver(myBall1)) {
 background(255, 0, 0);
}

Ed il gioco è fatto.

Trova l'errore

Anziché lasciarvi con un esercizio, questa volta ho un'altra sfida per voi. Il nostro programma funziona ma c'è un piccolo errore che non lo fa funzionare esattamente come ci eravamo prefissati. Sapete individuarlo?

Per aiutarvi allego un'immagine:

Trova l'errore

Esercizio: Bouncing Ball, parte 3 (OOP)

Se vi siete persi gli articoli precedenti, qui trovate la parte 1 e la parte 2 di questo esercizio. Con questo post non aggiungeremo niente di nuovo al nostro programma ma rivedremo per intero il codice per trasformarlo in una versione ad oggetti.

Bouncing Ball Object Oriented

Per prima cosa aggiungiamo una nuova Tab che chiameremo Ball, come la classe che creeremo:

class Ball {
 
}

Per non dimenticarci il constructor, aggiungiamo subito la sintassi necessaria:

class Ball {
 Ball() {
 }
}

A questo punto facciamo copia-incolla delle porzioni di codice che, nel nostro sketch principale, riguardano la nostra palla: ricordatevi di portare nella classe sia le variabili che le funzioni.

Questo è il risultato finale:

class Ball {
  int ellipseX;
  int ellipseY;
  int speedX;
  int speedY;

  Ball() {
    ellipseX = 0;
    ellipseY = height/2;
    speedX = 1;
    speedY = 1;
  }

  void display() {
    ellipse(ellipseX, ellipseY, 50, 50);
  }

  void move() {
    ellipseX = ellipseX + speedX;
    ellipseY = ellipseY + speedY;
  }

  void checkEdges() {
    if (ellipseX > width || ellipseX < 0) {
      speedX = speedX * -1;
    }
    if (ellipseY > height || ellipseY < 0) {
      speedY = speedY * -1;
    }
  }
}
Ball myBall;

void setup() {
  size(700, 500);
  myBall = new Ball();
}

void draw() {
  background(0);
  myBall.display();
  myBall.move();
  myBall.checkEdges();
}

Aggiungiamo constructor

Miglioriamo la nostra classe creando dei nuovi constructor a cui possiamo passare delle variabili. Come già fatto nell'esempio del post precedente, conviene sostituire il data type delle variabili da integer float.

class Ball {
  // VARIABILI
  float ellipseX;
  float ellipseY;
  float speedX;
  float speedY;
  
  // CONSTRUCTOR
  Ball() {
    ellipseX = random(width);
    ellipseY = random(height);
    speedX = 1;
    speedY = 1;
  }
  
  Ball(float _ellipseX) {
    ellipseX = _ellipseX;
    ellipseY = random(height);
    speedX = 1;
    speedY = 1;
  }
  
  Ball(float _ellipseX, float _ellipseY) {
    ellipseX = _ellipseX;
    ellipseY = _ellipseY;
    speedX = 1;
    speedY = 1;
  }
  
  Ball(float _ellipseX, float _ellipseY, float _speedX) {
    ellipseX = _ellipseX;
    ellipseY = _ellipseY;
    speedX = _speedX;
    speedY = 1;
  }
  
  Ball(float _ellipseX, float _ellipseY, float _speedX, float _speedY) {
    ellipseX = _ellipseX;
    ellipseY = _ellipseY;
    speedX = _speedX;
    speedY = _speedY;
  }
  
  // METODI
  void display() {
    ellipse(ellipseX, ellipseY, 50, 50);
  }

  void move() {
    ellipseX = ellipseX + speedX;
    ellipseY = ellipseY + speedY;
  }

  void checkEdges() {
    if (ellipseX > width || ellipseX < 0) {
      speedX = speedX * -1;
    }
    if (ellipseY > height || ellipseY < 0) {
      speedY = speedY * -1;
    }
  }
}

A questo punto non ci resta che sperimentare se funziona tutto correttamente provando a passare delle variabili alla nostra classe:

myBall = new Ball(random(width), random(height), 5, 10);

OOP: Classi e oggetti, parte 2

Ripartiamo da dove ci siamo fermati con l’ultimo post: abbiamo scritto la nostra prima classe e abbiamo creato il nostro primo oggetto. Nell’approfondimento di oggi su classi e oggetti parleremo di alcune questioni importanti: come mantenere pulito il codice quando si lavora con le classi, come passare parametri al constructor e, infine, come creare n oggetti.

Operazione pulizia: utilizzare le Tab

Car myCar;

void setup() {
  size(500, 500);
  myCar = new Car();
}

void draw() {
  background(255);
  myCar.display();
  myCar.move();
}


class Car {
  // Dati
  int carLength;
  int xPos;
  int yPos;
  int speed;

  // Constructor
  Car() {
    carLength = 10;
    xPos = 0;
    yPos = 200;
    speed = 1;
  }

  // Metodi
  void display() {
    rectMode(CENTER);
    fill(0);
    rect(xPos, yPos, carLength, 10);
  }

  void move() {
    xPos = xPos + speed;
  }
}

Il nostro codice ora è lungo 40 righe in tutto e la classe Car occupa la maggior parte dello spazio. Immaginate per un secondo di avere tra le mani un programma molto complesso, che utilizza tante tipologie di oggetti differenti. Sarebbe davvero problematico andare a cercare di volta in volta scorrendo in su e in giù la porzione di codice che si riferisce all’oggetto che vogliamo utilizzare.

Per fortuna Processing viene in nostro aiuto con una funzione molto comoda: le Tab.

Crea una nuova Tab su Processing

Cliccando sulla freccia che punta in basso accanto al nome del nostro sketch, si aprirà un menu con diverse opzioni. Clicchiamo su New Tab (su Mac la scorciatoia è ⇧⌘N). A questo punto il programma ci chiederà il nome che vogliamo dare alla nostra tab; dovendo spostare lì la classe Car, utilizziamo lo stesso nome sempre con l’iniziale maiuscola.

Una volta cliccato su OK, l’editor creerà un altro file .pde che verrà aggiunto automaticamente alla cartella dove abbiamo salvato il nostro sketch (la scorciatoia per vedere velocemente la cartella è ⌘K).

Sketch Folder

A questo punto facciamo copia-incolla del codice della classe nella nuova tab e proviamo a cliccare Run. Il programma dovrebbe aprirsi e funzionare esattamente come prima con la differenza che, ora, il codice del file principale – quello nominato sketch_160115a.pde in questo esempio – è molto più breve e pulito.

Passare parametri al constructor

La nostra classe Car è ora funzionale e pulita ma è ancora migliorabile: ho scritto più volte dell’importanza di utilizzare le variabili invece di parametri hard-coded ma il constructor che abbiamo ora genererà sempre oggetti con le stesse caratteristiche: la lunghezza sarà sempre pari a 10 pixel, la posizione di partenza sarà x = 0 e y = 200 e la velocità pari a 1.

La buona notizia è che possiamo inserire nella nostra classe più constructor mantenendo una sintassi simile a quella che già conosciamo; dobbiamo solo aggiungere, all’interno della parentesi tonda, le variabili che decidiamo di passare ai nostri oggetti.

In questo primo esempio, aggiungiamo la possibilità di modificare la lunghezza della nostra macchina.

class Car {
  // Dati
  int carLength;
  int xPos;
  int yPos;
  int speed;

  // Constructor
  Car() {
    carLength = 10;
    xPos = 0;
    yPos = 200;
    speed = 1;
  }
  
  // Secondo Constructor
  Car(int tempCarLength) {
    carLength = tempCarLength;
    xPos = 0;
    yPos = 200;
    speed = 1;
  }

  // Metodi
  void display() {
    rectMode(CENTER);
    fill(0);
    rect(xPos, yPos, carLength, 10);
  }

  void move() {
    xPos = xPos + speed;
  }
}

In questa nuova versione ho aggiunto alla classe un nuovo constructor che accetta un solo parametro di tipo integer. Quando il parametro viene passato devo utilizzare una variabile temporanea, motivo per cui ho inserito la variabile tempCarLength. La variabile temporanea dovrà poi essere assegnata alla variabile relativa all’interno del costructor: carLength = tempCarLength.

Questo è il momento in cui è necessario diventare molto ordinati e scrupolosi con i nomi che diamo alle nostre variabili, il rischio è di complicarci inutilmente la vita.

Ora che abbiamo un nuovo constructor, torniamo al nostro sketch principale e modifichiamo l’inizializzazione da così:

myCar = new Car();

a così:

myCar = new Car(25);

Proviamo a lanciare il nostro sketch.

Variabili al constructor

Il nostro rettangolo sarà ora lungo 25 pixel.

Cosa succede se proviamo a passare al nostro constructor una variabile di tipo float?

myCar = new Car(25.7);

Ovviamente ci verrà restituito un errore: The constructor “Car(float)” does not exist.

Constructor, constructor, constructor

Il prossimo passaggio sarà creare tanti constructor quanti sono i dati che il nostro oggetto contiene: nel nostro programma vorremmo, ad esempio, decidere anche la posizione x e y di partenza oltre, ovviamente, diversi valori di velocità. Possiamo fare anche un passaggio in più: aggiungiamo una nuova variabile che contenga anche il colore della macchina.

Vi invito a provare a modificare la classe per conto vostro e di non guardare subito il codice qui sotto. In questo modo capirete se, effettivamente, vi è tutto chiaro.

class Car {
  // Dati
  int carLength;
  float xPos;
  int yPos;
  float speed;
  color c;

  // Constructor
  Car() {
    carLength = 10;
    xPos = 0;
    yPos = 200;
    speed = 1;
    c = color(0);
  }
  
  // Secondo Constructor
  Car(int tempCarLength) {
    carLength = tempCarLength;
    xPos = 0;
    yPos = 200;
    speed = 1;
    c = color(0);
  }
  
  // Secondo Constructor
  Car(int tempCarLength, int tempXPos) {
    carLength = tempCarLength;
    xPos = tempXPos;
    yPos = 200;
    speed = 1;
    c = color(0);
  }
  
  Car(int tempCarLength, int tempXPos, int tempYPos) {
    carLength = tempCarLength;
    xPos = tempXPos;
    yPos = tempYPos;
    speed = 1;
    c = color(0);
  }
  
  Car(int tempCarLength, int tempXPos, int tempYPos, float tempSpeed) {
    carLength = tempCarLength;
    xPos = tempXPos;
    yPos = tempYPos;
    speed = tempSpeed;
    c = color(0);
  }
  
  Car(int tempCarLength, int tempXPos, int tempYPos, float tempSpeed, color tempColor) {
    carLength = tempCarLength;
    xPos = tempXPos;
    yPos = tempYPos;
    speed = tempSpeed;
    c = tempColor;
  }

  // Metodi
  void display() {
    rectMode(CENTER);
    fill(c);
    rect(xPos, yPos, carLength, 10);
  }

  void move() {
    xPos = xPos + speed;
  }
}

Sottolineo un paio di cose:

  1. Ho aggiornato la nostra classe senza toccare il codice del nostro sketch principale. Questa è la potenza della programmazione orientata agli oggetti: modificare porzioni di codice senza andare a intaccare le altre parti che compongono il programma.
  2. Ho utilizzato per la prima volta il datatype color. Non è niente di difficile ma, dal momento che non ho intenzione di spiegare come funziona in questo post, vi invito a leggere il manuale.
  3. Ho cambiato il datatype di speed in float e sono stato costretto a cambiarlo anche per xPos dal momento che nella funzione move() i due parametri vengono sommati. Se avessi lasciato xPos come int, Processing mi avrebbe restituito un errore.

Ora che la nostra classe è completa, possiamo sbizzarrirci a passare quanti parametri vogliamo, l’importante è  ricordarsi l’ordine dei parametri e i tipi di dati accettati:

myCar = new Car(25, 50, 200, 0.5, color(255, 255, 0));

Il bello è che possiamo utilizzare anche delle funzioni per passare i parametri. Vi ricordate di random?

myCar = new Car(25, 50, 200, random(5), color(random(255), random(255), random(255)));

Creiamo oggetti

Nell’introduzione agli oggetti avevo specificato che un punto di forza dell’OOP è poter creare più istanze dello stesso oggetto. Come possiamo, dunque, creare 3 macchine?

Riprendiamo in mano il nostro sketch principale e aggiungiamo altre due variabili di tipo Car chiamate myCar2 e myCar3, in setup() creiamo due nuove istanze degli oggetti e, in draw() ci assicuriamo di richiamare, per ciascuna, i metodi display() e move().

Car myCar, myCar2, myCar3;

void setup() {
  size(500, 500);
  myCar = new Car(25, 50, 200, random(5), color(random(255), random(255), random(255)));
  myCar2 = new Car(int(random(5, 50)), int(random(width)), int(random(height)), random(5), color(random(255), random(255), random(255)));
  myCar3 = new Car(int(random(5, 50)), int(random(width)), int(random(height)), random(5), color(random(255), random(255), random(255)));
}

void draw() {
  background(255);
  myCar.display();
  myCar.move();
  
  myCar2.display();
  myCar2.move();
  
  myCar3.display();
  myCar3.move();
}

Premiamo su Run:

Abbiamo creato 3 oggetti Car

Fino a qui tutto bene, ma, a questo punto la domanda che sorge spontanea è: se volessimo creare decinecentinaia di oggetti? Dovremmo impazzire con il copia-incolla. Chiaramente esiste una soluzione più comoda: utilizzare gli array che, per l’appunto, saranno il prossimo argomento che tratteremo.

Compiti a casa

È arrivato il momento di dimostrare di aver capito come funziona la programmazione ad oggetti: riprendete in mano l’esercizio Bouncing Ball (parte 1 e parte 2) e modificate il codice per renderlo object-oriented.

OOP: Sintassi di classi e oggetti

La settimana scorsa abbiamo fatto un’introduzione generale alla programmazione orientata agli oggetti; con questo post entreremo nello specifico analizzando la sintassi corretta da utilizzare quando si scrive una classe e quando si usa un oggetto in Processing.

Sintassi della classe

Ricordo che per classe intendiamo il template di partenza che utilizzeremo per creare nuovi oggetti. Per creare una nuova classe abbiamo solo bisogno di assegnargli un nome ma, se vogliamo sfruttare al massimo l’OOP, ciascuna classe avrà le seguenti caratteristiche: nome, dati, constructor metodi.

class Car {
  // Dati
  int carLength;
  int xPos;
  int yPos;
  int speed;
  
  // Constructor
  Car() {
    carLength = 10;
    xPos = 0;
    yPos = 200;
    speed = 1;
  }
  
  // Metodi
  void display() {
    rectMode(CENTER);
    fill(0);
    rect(xPos, yPos, carLength, 10);
  }
  
  void move() {
    xPos = xPos + speed;
  }
}

Abbiamo scritto la nostra prima classe: Car. Per prima cosa sottolineo che le classi hanno sempre la prima lettera maiuscola: questo serve per differenziarle da tutti gli altri componenti che possiamo trovare in un programma (variabili, funzioni, ecc…).

Come potete vedere, la classe ha dei dati al suo interno che scriviamo sotto forma di variabili: la lunghezza dell’oggetto-macchina, la posizione X e Y di partenza e la velocità. Tali dati sono solo dichiarati ma non inizializzati. Per questo ci serve il constructor che è quella funzione speciale che serve per creare l’oggetto vero e proprio: per funzionare il constructor deve avere lo stesso nome della classe.

Nell’esempio qui sopra, ogni volta che creeremo l’oggetto Car gli assegneremo di default i dati del constructor quindi una lunghezza di 10 pixel, x = 0, y = 200 e velocità pari a 1.

Infine ci sono i metodi ovvero le funzionalità che vogliamo dare al nostro oggetto: in questo esempio la nostra macchina sarà visualizzata sullo schermo (display) e poi si muoverà (move).

Sintassi dell’oggetto

Car myCar;

void setup() {
  size(500, 500);
  myCar = new Car();
}

void draw() {
  background(255);
  myCar.display();
  myCar.move();
}

Nella prima riga stiamo dichiarando una variabile globale il cui nome è myCar il cui data-type non sarà uno dei classici incontrati finora (integer, float, stringa, ecc…) ma sarà un oggetto Car.

All’interno del blocco di setup() inizializziamo la nostra variabile myCar creando una nuova istanza dell’oggetto. In pratica con la sintassi myCar = new Car() stiamo richiamando il constructor presente all’interno della classe. Con una sola riga di codice abbiamo assegnato alla nostra myCar una serie di valori: carLength = 10, xPos = 0, yPos = 200; speed = 1 senza doverli riscrivere.

Nel ciclo draw() richiamiamo i metodi della classe. Da notare che a differenza delle funzioni che abbiamo visto fino ad ora, dobbiamo utilizzare la cosiddetta dot syntax ovvero myCar.display() perché display è un metodo presente all’interno di myCar. Se scrivessimo solo display(); chiaramente non funzionerebbe.

Il nostro primo programma ad oggetti

Car myCar;

void setup() {
  size(500, 500);
  myCar = new Car();
}

void draw() {
  background(255);
  myCar.display();
  myCar.move();
}


class Car {
  // Dati
  int carLength;
  int xPos;
  int yPos;
  int speed;

  // Constructor
  Car() {
    carLength = 10;
    xPos = 0;
    yPos = 200;
    speed = 1;
  }

  // Metodi
  void display() {
    rectMode(CENTER);
    fill(0);
    rect(xPos, yPos, carLength, 10);
  }

  void move() {
    xPos = xPos + speed;
  }
}

Ecco il codice completo del nostro programma. Potete notare come la classe costituisca un nuovo blocco di codice all’interno del programma. Il codice diventa più pulito e facile da leggere perché all’interno di setup e draw troviamo pochissime righe di codice. Copiando e incollando il codice e cliccando su Run vedrete un quadratino di 10x10px che si muoverà sullo schermo.

Mi rendo conto che in alcuni punti la spiegazione possa essere arzigogolata ma spero che vi sia tutto chiaro; potete provare a cambiare alcune porzioni di codice per verificare se tutto vi torna.

Introduzione agli oggetti

È finalmente arrivato il momento di cominciare a parlare di programmazione orientata agli oggetti ma, prima di addentrarci nel codice e modificare i nostri sketch, è importante dare una definizione chiara e semplice di che cosa sono gli oggetti e di come li possiamo utilizzare.

Questo post, quindi, non conterrà esempi pratici ma fornirà un’introduzione generale all’argomento. Ho deciso di muovermi in questo modo perché quando mi sono trovato ad affrontare per la prima volta l’OOP ho faticato a capire il reale vantaggio di un approccio ad oggetti. Oggi invece, non potrei farne a meno.

Partiamo con una buona notizia: per utilizzare gli oggetti non dobbiamo imparare nulla di nuovo rispetto a quanto fatto fino ad ora. Utilizzeremo variabili, controlli condizionali, loop e funzioni. Se siete arrivati a questo punto e avete ancora dei dubbi in merito anche solo ad uno di questi argomenti, il mio consiglio è di fermarsi ora e andare a rileggere i vecchi post. Se, invece, è tutto chiaro, procediamo!

Oggetti: questione di astrazione

Nella realtà di tutti i giorni siamo abituati ad avere a che fare con oggetti specifici ciascuno con caratteristiche peculiari che dipendono, in gran parte, dalla marca e dal modello che possediamo. Questi oggetti, però, possono essere astratti a un livello più alto: pensiamo, ad esempio a una macchina.

Se potessi leggere nelle vostre menti, vedrei che ciascuno di voi sta pensando a una macchina differente dagli altri ma che, in quanto oggetto-macchina, ha delle caratteristiche comuni a tutte le altre: ad esempio il numero di ruote sarà uguale per tutti mentre il colore della carrozzeria sarà differente.

È importante notare come l’oggetto-macchina possa avere dei dati (colore, lunghezza, numero porte, …) e delle funzioni (si muove in avanti, si muove indietro, …).

Facciamo un passo in più: l’astrazione della macchina non rappresenta di per sé una macchina vera e propria. Il modello-macchina astratto funge da template. In programmazione, l’oggetto astratto viene chiamato classe. Ciascuna macchina che prenderà come base il modello astratto ma avrà caratteristiche peculiari sarà a tutti gli effetti un oggetto vero e proprio. In programmazione, quando richiamiamo la classe per costruire un nuovo oggetto stiamo creando un’istanza della classe.

Ricapitolando

Abbiamo un modello astratto che fungerà da «template» per tutti gli oggetti che andremo a creare che chiamiamo classe mentre creando un’istanza della classe creiamo effettivamente un oggetto.

Cosa c’è di nuovo?

Fino a qui tutto ok, ma qual è la vera novità? Le variabili legate agli oggetti, così come le funzioni legate alle azioni che questi oggetti devono compiere all’interno del nostro programma, saranno all’interno della classe.

Con la programmazione a oggetti il codice si semplificherà ulteriormente perché non andremo a «sporcare» il codice con informazioni inutili. Ci basterà richiamare la classe perché ciascun oggetto avrà tutto quello di cui necessita al suo interno.

Nel prossimo post vedremo la sintassi corretta da utilizzare sia delle classi che degli oggetti e poi, finalmente, cominceremo a sporcarci un po’ le mani.