580 likes | 694 Views
Introduzione ai linguaggi compilati orientati ad oggetti. Alessandra Doria, Napoli Vincenzo Innocente , CERN Luca Lista, Napoli. Programmazione procedurale. Uno dei principali problemi del software è la sua evoluzione e la sua manutenzione
E N D
Introduzione ai linguaggi compilati orientati ad oggetti Alessandra Doria, Napoli Vincenzo Innocente, CERN Luca Lista, Napoli Vincenzo Innocente - Corso breve OO
Programmazione procedurale • Uno dei principali problemi del software è la sua evoluzione e la sua manutenzione • specialmente in grossi progetti come un esperimento di HEP • Esempi con linguaggi procedurali (Fortran): • Cosa succede quando il codice viene modificato • Dipendenze all’interno del codice Vincenzo Innocente - Corso breve OO
Un esempio semplice • Un esempio “elegante”: copiare una sequenza di caratteri dalla tastiera alla stampante SUBROUTINE COPY LOGICAL READKB CHARACTER C DO WHILE (READKB(C)) CALL WRTPRN(C) ENDDO RETURN • Questo codice dovrà prima o poi essere modificato (aggiornamenti, estensioni, richieste dagli utenti, ecc.) Vincenzo Innocente - Corso breve OO
Modifiche dei requisiti • Una modifica un po’ meno elegante:scrivere anche su un file SUBROUTINE COPY(FLAG) LOGICAL READKB INTEGER FLAG CHARACTER C DO WHILE (READKB(C)) IF (FLAG .EQ. 1) CALL WRTPRN(C) ELSE CALL WRTFL(C) ENDIF ENDDO RETURN Vincenzo Innocente - Corso breve OO
Evoluzione incontrollata SUBROUTINE COPY(FLAG1, FLAG2) LOGICAL READKB, READFL INTEGER FLAG1, FLAG2 LOGICAL CONT CHARACTER C 10 IF (FLAG1 .EQ. 1) THEN CONT = READKB(C) ELSE CONT = READFL(C) ENDIF IF (CONT) THEN IF (FLAG2 .EQ. 1) THEN CALL WRTPRN(C) ELSE CALL WRTFL(C) ENDIF GOTO 10 ENDIF RETURN • Un’altra modifica per niente elegante:leggere anche de un file Vincenzo Innocente - Corso breve OO
Descrizione dei dati Idea: perché non usare una function? • Esempio: cinematica relativistica COMMON /MYDATA/ P1(4), P2(4), + P3(4), P4(4) REAL P1(4), P2(4), P3(4), P4(4) COSTHETA12 = (P1(1)*P2(1) + P1(2)*P2(2) + + P1(3)*P2(3))/... COSTHETA13 = (P1(1)*P3(1) + P1(2)*P3(2) + + P1(3)*P3(3))/... COSTHETA14 = (P1(1)*P4(1) + P1(2)*P4(2) + + P1(3)*P4(3))/... FUNCTION COSTHETA(P1, P2) REAL P1(4), P2(4) COSTHETA = (P1(1)*P2(1) + P1(2)*P2(2) + + P1(3)*P2(3))/... END COMMON /MYDATA/ P1(4), P2(4), + P3(4), P4(4) REAL P1(4), P2(4), P3(4), P4(4) COSTHETA12 = COSTHETA(P1, P2) COSTHETA13 = COSTHETA(P1, P3) COSTHETA14 = COSTHETA(P1, P4) Vincenzo Innocente - Corso breve OO
Evoluzione del codice • Se cambia il formato del common block? COMMON /MYDATA/ P1(4), P2(4), + P3(4), P4(4) COMMON /MYDATA/ P(4), E(4), + THETA(4), PHI(4) • Bisogna cambiare la funzione (gli argomenti sono diversi) FUNCTION COSTHETA1(THETA1, THETA2, + PHI1, PHI2) COSTHETA1 = SIN(THETA1)*SIN(THETA2) * + COS(PHI1-PHI2) + COS(THETA1)*COS(THETA2) END • …e il codice! COMMON /MYDATA/ P(4), E(4), + THETA(4), PHI(4) COSTHETA12 = COSTHETA1(THETA(1),THETA(2), + PHI(1), PHI(2)) COSTHETA13 = COSTHETA1(THETA(1),THETA(3), + PHI(1), PHI(3)) COSTHETA14 = COSTHETA1(THETA(1),THETA(4), + PHI(1), PHI(4)) Vincenzo Innocente - Corso breve OO
Il concetto di dipendenza • Nell’esempio precedente il codice di analisi (“alto livello”) dipende dai dettagli della struttura dati (“basso livello”). FUNCTION COSTHETA(P1, P2) REAL P1(4), P2(4) COSTHETA = (P1(1)*P2(1) + P1(2)*P2(2) + + P1(3)*P2(3))/... END COSTHETA dipende dalla struttura dei dati P1 e P2 COMMON /MYDATA/ P1(4), P2(4), + P3(4), P4(4) COSTHETA12 = COSTHETA(P1, P2) COSTHETA13 = COSTHETA(P1, P3) COSTHETA14 = COSTHETA(P1, P4) Il codice di analisi dipende dalla struttura del common block MYDATA Vincenzo Innocente - Corso breve OO
C++/Object Oriented • Riduce la dipendenza del codice di alto livello dalla rappresentazione dei datiPermette il riutilizzo del codice di alto livello • Nasconde i dettagli di implementazione Vincenzo Innocente - Corso breve OO
Kalman.inc Filter.f PARAMETER (NPLAN = 8, NSTOP = NPLAN-1, + NSTOP5 = 5*NPLAN ) COMMON /GCFIT/ + CSIX(6,0:NSTOP),CSIY(6,0:NSTOP) + ,CSIZ(6,0:NSTOP) + ,WW(5,5,0:NSTOP),DDT(5,5,0:NSTOP) + ,VV(5,5,0:NSTOP),SS(5,5,0:NSTOP) + ,CC(5,5,0:NSTOP) + ,CHI2,CHI2N,CHI2T,CHI2M + ,PLANI(3,4,0:NSTOP) DOUBLE PRECISION + CSIX ,CSIY ,CSIZ + ,WW ,DDT + ,VV ,SS + ,CC + ,CHI2,CHI2N,CHI2T,CHI2M SUBROUTINE FILTER(JSTOP,IFAIL) INTEGER JSTOP, IFAIL #include “Kalman.inc” DOUBLE PRECISION YDUM(5) * ** filter * CALL DVADD(25,WW(1,1,JSTOP),WW(2,1,JSTOP), + VV(1,1,JSTOP),VV(2,1,JSTOP), + CC(1,1,JSTOP),CC(2,1,JSTOP)) CALL DSINV(5,CC(1,1,JSTOP),5,IFAIL) IF ( IFAIL.NE.0 ) THEN 1 PRINT *,'DSINV IFAIL',IFAIL,' AT PLANE ',JSTOP CALL VZERO(CC(1,1,JSTOP),50) RETURN ENDIF CALL DMMPY(5,5,VV(1,1,JSTOP),VV(1,2,JSTOP),VV(2,1,JSTOP), + CSIZ(1,JSTOP),CSIZ(2,JSTOP), + YDUM(1), YDUM(2)) CALL DMMPA(5,5,WW(1,1,JSTOP),WW(1,2,JSTOP),WW(2,1,JSTOP), + CSIY(1,JSTOP),CSIY(2,JSTOP), + YDUM(1), YDUM(2)) CALL DMMPY(5,5,CC(1,1,JSTOP),CC(1,2,JSTOP),CC(2,1,JSTOP), + YDUM(1), YDUM(2), + CSIX(1,JSTOP),CSIX(2,JSTOP)) CSIX(6,JSTOP) = CSIY(6,JSTOP) * CHI2 DO J = 1,5 DO K=1,5 CHI2 = CHI2 + + (CSIX(K,JSTOP)-CSIZ(K,JSTOP))*VV(K,J,JSTOP)* + (CSIX(J,JSTOP)-CSIZ(J,JSTOP)) + + (CSIX(K,JSTOP)-CSIY(K,JSTOP))*WW(K,J,JSTOP)* + (CSIX(J,JSTOP)-CSIY(J,JSTOP)) ENDDO ENDDO * END Dati globali Modello dei dati esplicito Sintassi oscura Tipo non controllato Vincenzo Innocente - Corso breve OO
KalmanStep.h KalmanStep.cc class KalmanStep { public: bool propagate(const KalmanStep& previous); bool filter() ; bool smooth(const KalmanStep& next); private: Vector5 csix; SimMatrix5 cc; SimMatrix5 ss; Vector5 csiy; SimMatrix5 ww; Vector5 csiz; SimMatrix5 vv; Matrix5 ddt; Plane plane; double chi2; }; bool KalmanStep::filter() { bool fail = false; cc = ww+vv; cc.invert(fail); if (fail) { cc.zero(); return !fail;} csix = cc*(vv*csiz + ww*csiy); chi2 += (csix-csiz)*vv*(csix-csiz)+ (csix-csiy)*ww*(csix-csiy); return !fail; } Tipo controllato o convertito Sintassi “naturale” Modello dei dati nascosto Dati incapsulati Vincenzo Innocente - Corso breve OO
Classi e oggetti • Definizione di nuovi tipi (oltre a int, float, double) come: • numeri complessi, • vettori, • matrici, . . . • ma anche: • tracce, • superfici, • elementi di rivelatori, • cluster, . . . • Gli oggetti permettono di modellare una problema che rappresenti la realtà Vincenzo Innocente - Corso breve OO
Concetti base dell’OO • Classi ed oggetti • Incapsulamento • Relazione di ereditarietà • Polimorfismo • Programmazione Generica (C++) Vincenzo Innocente - Corso breve OO
Classi e Oggetti • Un esempio di programma “orientato ad oggetti”: un videogioco Vincenzo Innocente - Corso breve OO
Cliente Soldato Vincenzo Innocente - Corso breve OO
FORTRANvsC/C++ • Sintassi F77 e C a confronto In C/ C++ non è necessario un particolare formato il codice PROGRAM TESTC esempio di programma ... END int main() {// esempio di programma ... return 0; // fine} spazi... Il C/ C++ è case sensitive Istruzioni separate da “;” INTEGER I INTEGER*4 J REAL X REAL*8 D int i;long j;float x;double d; Vincenzo Innocente - Corso breve OO
FORTRANvsC/C++ • Controllo di flusso del programma DO I = 1, 10 . . . ENDDO IF (I.EQ.10 .AND. J.GT.4 .OR. X) THEN . . . ENDIF DO WHILE(X .NE. 5) . . . ENDDO for ( i = 1; i <= 10; i++ ) { . . .} if ( i == 10 && j > 4 || x ) { . . .} while( x != 5 ){ . . .} Vincenzo Innocente - Corso breve OO
j ptr 12 24 Puntatori • Riferimento ad una locazione di memoria int main(){ int j = 12; return 0;} int *ptr = &j; #include <iostream.h> cout << *ptr << endl; j = 24; cout << *ptr << endl; cout << ptr << endl; 24 0x7b03a928 12 indirizzo di memoria Vincenzo Innocente - Corso breve OO
j ptr 12 Puntatori • Puntatore nullo #include <iostream.h> int main(){ int j = 12; int *ptr = 0; cout << *ptr << endl; // crash ! return 0;} Segmentation violation (core dumped) Vincenzo Innocente - Corso breve OO
ptr 12 Puntatori: allocazione dinamica • Riferimento ad una locazione di memoria #include <iostream.h> int main(){ int *ptr = new int; *ptr = 12; cout << *ptr << endl;delete ptr; return 0;} • Attenzione: • Non usare delete fa accumulare locazioni di memoria inutilizzate (memory leak) • Utilizzare puntatori prima del new o dopo il delete causa il crash del programma Vincenzo Innocente - Corso breve OO
Classi astratte • Esempio classico: Shape • Tutti oggetti nella finestra hanno comportamenti comuni che possono essere considerati in astratto: • disegna, sposta, ingrandisci, etc. Vincenzo Innocente - Corso breve OO
Nome della classe Circle.h Costruttore Distruttore Point2d: classe che rappresenta un punto in 2 dimensioni. Main.cc Circle.cc #include “Circle.h” void Circle::draw() const { const int numberOfPoints = 100; float x[numberOfPoints], y[numberOfPoints]; float phi = 0, deltaPhi = 2*M_PI/100; for ( int i = 0; i < numberOfPoints; ++i ) { x[i] = center_.x() + radius_ * cos( phi ); y[i] = center_.y() + radius_ * sin( phi ); phi += dphi; } polyline_draw(x, y, numberOfPoints ); } void Circle::moveAt( const Point2d& p ) { cancel(); center_ = p; draw(); } void Circle::scale( double s ) { cancel(); radius_ *= s; draw(); } Circle::Circle( Point2d c, double r ) : center_( c ), radius_( r ) { draw(); } Circle::~Circle() { cancel(); } #include “Circle.h” int main() { Circlec( Point2d(10, 10), 5 ); c.draw(); c.moveAt(Point2d(20, 30)); return 0; } Interfaccia Pubblica Metodi: operazioni sugli oggetti “Dati” privati (Attributi, membri) Punto e virgola! Cerchio class Circle { }; public: Circle(Point2d center, double radius); ~Circle(); void moveAt(const Point2d & p); void moveBy(const Point2d & p); void scale(double s); void rotate(double phi); void draw() const; void cancel() const; private: Point2d center_; double radius_; Vincenzo Innocente - Corso breve OO
Square.h Square.cc class Square { public: Square(const Point2d&, const Point2d&); ~Square(); void moveAt( const Point2d& p ); void moveBy( const Point2d& p ); void scale( double s ); void rotate( double phi ); void draw() const; void cancel() const; private: Point2d center_; Vector2d centerToUpperCorner_; }; #include “Square.h” void Square::draw() const { float x[4], y[4]; Vector2d delta( centerToUpperCorner_ ); for ( int i = 0; i < 4; i++ ) { Point2d corner = center_ + delta; x[i] = corner.x(); y[i] = corner.y(); delta.rotate( M_PI_2 ); } polyline_draw(x, y, 4); } void Square::rotate( double phi ) { cancel(); centerToUpperCorner_.rotate( phi ); draw(); } Square::Square(const Point2d& lowerCorner, const Point2d& upperCorner ) : center_( median(lowerCorner, upperCorner) ), centerToUpperCorner_( upperCorner - center_ ){ draw(); } void Square::scale( double s ) { cancel(); centerToUpperCorner_ *= s; draw(); } Quadrato centerToUpperCorner_ upperCorner loweCorner Vincenzo Innocente - Corso breve OO
Main.cc #include “Circle.h” #include “Square.h” int main() { Circle c1( Point2d(2.,3.), 4.23, ); Square r1( Point2d(2.,1.), Point2d(4.,3.) ); Circle * circles[ 10 ]; for ( int i = 0; i < 10; ++i ) { circles[ i ] = new Circle( Point2d(i,i), 2. ); } for ( int i = 0; i < 10; ++i ) circles[ i ]->draw(); return 0; } Codice Applicativo (Client) Costruisce un vettore di puntatori a cerchi, crea oggetti in memoria e salva i loro puntatori nel vettore. Itera sul vettore e invoca draw() per ogni elemento Come gestire cerchi e quadrati insieme? Vincenzo Innocente - Corso breve OO
Polimorfismo Tutte le Shapes hanno la stessa interfaccia: draw, pick, move, fillColor..., ma ogni sottotipo diverso può avere la usa personale implementazione Vincenzo Innocente - Corso breve OO
Shape.h Square.h Main.cc class Shape { public: Shape() { } virtual~Shape() { } virtual void moveAt( const Point2d& ) = 0; virtual void scale( double s ) = 0; virtual void rotate( double phi ) = 0; virtual void draw() const = 0; virtual void cancel() const = 0; }; #include “Shape.h” class Square: publicShape { // …. Il resto tutto uguale a prima }; #include “Circle.h” #include “Square.h” int main() { Shape * shapes[ 10 ]; int index = 0; for ( int i = 0; i < 10; i++ ) { Shape * s; s = new Circle( Point2d(i, i), 2.) ); shapes[ index ++ ] = s; s = new Square( Point2d(i, i), Point2d(i+1, i+2)) ); shapes[ index ++ ] = s; } for ( int i = 0; i < 10; i++ ) shapes[ i ]->draw(); return 0; } Interfaccia astratta Interfaccia di metodi puramente virtuali Vincenzo Innocente - Corso breve OO
CenteredShape.h Square.h Class CenteredShape: public Shape { public: CenteredShape( Point2d c ) : center_( c ) { /*draw();*/ } ~Circle() { /*cancel();*/ } void moveAt( const Point2d& ); void moveBy( const Vector2d& ); virtual void scale( double ) = 0; virtual void rotate( double ) = 0; virtual void draw() const = 0; virtual void cancel() const = 0; protected: Point2d center_; }; #include “CenteredShape.hh” class Square : public CenteredShape { public: Square( Point2d lowerCorner, Point2d upperCorner ) : CenteredShape( median(lowerCorner, upperCorner) ), touc_(upperCorner - center_) { draw(); } ~Square() { cancel(); } virtual void scale( double s ) { cancel(); centerToUpperCorner_ *= s; draw(); } virtual void rotate( double phi ); virtual void draw() const; virtual void cancel() const; private: Vector2d touc_; }; Ereditarietà e riuso del codice Non si possono chiamare metodi virtuali in costruttori e distruttori (troppo presto, troppo tardi) Vincenzo Innocente - Corso breve OO
Modello UML Vincenzo Innocente - Corso breve OO
P.h Main.cc class P { public: P(int ix,int iy):x(ix),y(iy){} bool operator<(const P& b) const { return y<b.y ||( y==b.y && x<b.x ); } private: float x; float y; }; int main() { float a = min(3.,2.); int i = min(2,3); P p1(1.,2.), p2(3.,1.); P p3 = min(p1,p2); return 0; } Programmazione generica Funzioni Generiche template<class T> inline T min(const T& a, const T& b) { return a < b ? a:b; } “<” deve essere definito per “T” Usa min<float> Usa min<P> Vincenzo Innocente - Corso breve OO
Vector3d.h Main.cc template <class T> class Vector3d { public: Vector3d(const T*a) { copy(a,a+3,&x[0]); } Vector3d<T>& operator+=(const Vector3d<T>& b) {x[0]+=b.x[0]; x[1]+=b.x[1]; x[2]+=b.x[2]; return *this;} private: T x[3]; }; #include “vector3d.h” int main() { Vector3d<float> a, b,c; c+=b+=a; Vector3d<complex> c1, c2; c2+=c1; return 0; } Programmazione generica Classi Generiche “copy” è una funzione generica di STL Ritorna se stesso per permettere la concatenazione di operatori Vincenzo Innocente - Corso breve OO
La libreria standard: std (STL) • Contenitori generici: • vector, list, set, map, “string” • Iteratori • puntatori “intelligenti” nei contenitori generici • Funzioni generiche • copy, merge, find, sort, swap,… • agiscono su iteratori Vincenzo Innocente - Corso breve OO
Main.cc #include <vector> int main() { vector<int> v; // creamo un vettore di interi vuoto cout << v.size() << endl; // stampa dimensione di v: zero for ( int i = 0; i != 10; ++i ) // un loop da 0 a 9 v.push_back( i ); // aggiungiamo un intero in coda a v cout << v.size() << endl; // stampa dimensione di v: 10 // creiamo un iteratore costante per un vettore di interi: // psi comporta come un “const int *” a tutti gli effetti vector<int>::const_iterator p; for ( p = v.begin(); p != v.end(); ++p ) // “itera dall’inizio alla fine di v” cout << (*p) << “ “; cout << endl; return 0; } Un semplice vettore Vincenzo Innocente - Corso breve OO
begin() end() p p p p p p Un semplice vettore ... 0 1 2 9 Vincenzo Innocente - Corso breve OO
Main.cc #include “Circle.h” #include “Square.h” #include <vector> int main() { vector<Shape *>vs; // un vettore di puntatori a Shapes for ( int i = 0; i != 10; ++i ) { // aggiungiamo un puntatore ad un nuovo cerchio vs.push_back(new Circle(Point2d(i, i), 2.)); // aggiungiamo un puntatore ad un nuovo quadrato vs.push_back(new Square(Point2d(i, i), Point2d(i + 1, i + 2))); } // iteratore: essenzialmente un puntatore a Shape* ossia un Shape** vector<Shape *>::const_iteratorp; for ( p = vs.begin(); p != vs.end(); ++p ) // loop sull’intero vettore (*p)->draw(); // disegniamo ogni Shape return 0; } Vettore di classe astratta Shape* Vincenzo Innocente - Corso breve OO
Concetti Classici Riveduti • Relazioni tra oggetti • Decomposizione funzionale in una classe responsabilità dei metodi • Decomposizione funzionale tra classi responsabilità delle classi Vincenzo Innocente - Corso breve OO
Superfici e traiettorie • Nel tracking spesso è necessario calcolare intersezioni tra curve (tracce) e superfici (elementi di detector) Vincenzo Innocente - Corso breve OO
Line.h Helix.h Trajectory.h #include “Trajectory.h” class Line : public Trajectory { public: virtualPointposition(double s); virtualVectordirection(double s); public: Point origin_; Vector direction_; }; #include “Trajectory.h” class Helix : public Trajectory { public: virtualPointposition(double s); virtualVectordirection(double s);}; class Trajectory { public: virtualPointposition(double s) = 0; virtualVectordirection(double s) = 0; }; Superfici e traiettorie • Interfaccia delle diverse Trajectory Vincenzo Innocente - Corso breve OO
Trajectory.cc Line.cc Helix.cc #include “Trajectory.h” // … vuoto ... #include “Line.h” Line::Line(const Point& o, constVector& d) : origin_( o ), direction_( d.unit() ) { } PointLine::position(double s) { return ( origin_ + s * direction_ ); } #include “Helix.h” Helix::Helix() { } PointHelix::position(double s) { // implementazione } Superfici e traiettorie • Implementazione Vincenzo Innocente - Corso breve OO
Plane.h Surface.h Cylinder.h class Surface { public: virtualdistance(const Point& p) = 0; virtualderDist(const Point& p, const Vector& r) = 0; }; #include “Surface.h” class Plane : public Surface { public: virtualdistance(const Point& p); virtualderDist(const Point& p, const Vector& r); protected: Point origin_; Vector norm_; double dist_; }; #include “Surface.h” class Cylinder : public Surface { public: virtualdistance(const Point& p); virtualderDist(const Point& p, const Vector& r);}; Superfici e traiettorie • Interfaccia delle varie Surface distanza (con segno) di un punto dalla superficie Vincenzo Innocente - Corso breve OO
Plane.cc Cylinder.cc Surface.cc #include “Plane.h” Plane::distance(const Point& p) { return ( _dist - ( (p - origin_) * direction_) ); } Plane::derDist(const Point& p, const Vector& r) { return - r * _direction; } #include “Cylinder.h” Cylinder::distance(const Point& p) { /* . . . */ } Cylinder::derDist(const Point& p, const Vector& r) { /* . . . */ } #include “Surface.h” // vuoto Superfici e traiettorie • Surface è una classe astratta Vincenzo Innocente - Corso breve OO
Intersection.h class Surface; class Trajectory; class Intersection { public: Intersection(Surface* s, Trajectory* t) surface_(s), trajectory_(t) {} Pointintersect(double s1, double s2); protected: double sIntersect(double s1, double s2); Surface* surface_; Trajectory* trajectory_; }; Superfici e traiettorie • Interfaccia di Intersection forward class declaration Vincenzo Innocente - Corso breve OO
Intersection.cc #include “Intersection.h” #include <math.h>#include “Surface.h”#include “Trajectory.h” const int maxIterations 20 const double sMax 1.e+6 const double accuracy1.e-3 double Intersection::sIntersect(double s1, double s2) { // algoritmo diNewton-Raphson double s = s1; double maxS = max(s1, s2); double minS = min(s1, s2); double d, delta; for( int j = 0; j < maxIterations; j++ ) { Point p = _trajectory->position( s ); d = surface_->distance( p ); delta = surface_->derDist( p, trajectory_->direction( s ) ); double ds = - d / delta; double test = s + ds; Superfici e traiettorie • Implementazione dell’algoritmo // controlla che test è tra s1 e s2 if( (s1 - test) * (test - s2) < 0.0 ) { if ( s1 < s2 ) s += abs( d ); else s -= abs( d ); if( s > maxS || s < minS ) return sMax; } else s = test; if( abs(d) < accuracy ) return s; } return sMax; } PointIntersection::intersect(double s1, double s2) { return trajectory_->position(sIntersect(s1, s2)); } Vincenzo Innocente - Corso breve OO
Superfici e traiettorie • Intersection usa solo: • I metodi position e direction di un’oggetto Trajectory • I metodi distance e derDist di un oggetto Surface • E’ possibile aggiungere una nuova classe che modellizza una nuova Trajectory o una nuova Surface e Intersection continua a funzionare senza modificare una linea di codice! • E’ possibile rendere anche Intersection astratto... Vincenzo Innocente - Corso breve OO
“Open/Closed principle” • Un buon codice deve essere • aperto ad estensioni • chiuso a modifiche • Modificare un codice funzionante può introdurre bachi… • L’Object Oriented, con il meccanismo delle classi virtuali, permette di applicare questo principio Vincenzo Innocente - Corso breve OO
Disegno a oggetti:Modello di Hardware DAQ Costruiamo un modello del Hardware per un sistema di acquisizione • “Use Cases”: • gestione delle parti (dove sono, a chi appartengono) • simulazione (potenza dissipata, spazio occupato) • controllo on-line (on/off, temperatura, voltaggio) • DAQ (questi dati da dove vengono?) • calibrazione (piedistalli, guadagni, fattori di conversione) Vincenzo Innocente - Corso breve OO
Chi sono i giocatori? • I componenti Hardware: Racks, crates, moduli di vario tipo e foggia • “Utenti” (persone, displays, interfacce) conviene avere un “corrispondente” nel modello Primi candidati a classi e oggetti Vincenzo Innocente - Corso breve OO
Un primo modello Vincenzo Innocente - Corso breve OO
Calcolo della potenza in un rack Vincenzo Innocente - Corso breve OO
La base di un modello composto Vincenzo Innocente - Corso breve OO
DaqLeaf.h DaqComponent.h #include “DaqComponent.h” class DaqLeaf: public DaqComponent { public: explicit DaqLeaf( float ip = 0 ): power_(ip) {} virtual float power() const { return power_;} } protected: float power_; }; class DaqComposite; // forward declaration class DaqComponent { public: DaqComponent() : parent_(0) {} virtual float power() const = 0; protected: DaqComposite * parent_; }; Codice del modello composto Vincenzo Innocente - Corso breve OO