DAM-M3-UF4. Conceptes d'Orientació a Objectes

De Wiki IES Marianao. Departament Informàtica
La revisió el 22:47, 5 set 2012 per Alex (Discussió | contribucions) (Herència)

Dreceres ràpides: navegació, cerca

torna M3 - Programació

Els pilars de la OO

  • Encapsulament i Ocultació. Restricció d'accés a les dades
  • Composició. Relació entre objectes
  • Herència. Relació entre classes
  • Polimorfisme. Determinació del comportament en temps d'execució


Encapsulament. Ocultació

La programació orientada a objectes es basa en el principi de que la classe ha de tenir el control total sobre les variables dels seus objectes, tant per consultar-les com per modificar-les.

Això implica que la classe ha d’establir qualsevol operació que es vulgui fer sobre els seus objectes i les seves variables, impedint que externament es puguin realitzar operacions no definides. (Ocultació). En general ocultant l'accés directe a la informació que conté l'objecte, les dades.

Cada objecte manté el seu estat i el seu comportament particulars, i alhora només mostra a l’exterior la informació necessària per tal que els altres objectes puguin interactuar amb ell. (Encapsulament).

El conjunt d’operacions / atributs que els objectes mostren per tal que s’interactuï amb ells s’anomena Interfase.

D’aquesta manera es protegeix l’objecte de canvis en el seu estat de manera incoherent o inesperada i s’amaga la implementació de les seves operacions, així també es poden fer canvis que mentre no modifiquin la interfase seran transparents a la resta del Sistema.


http://es.scribd.com/doc/52944613/17/Encapsulacion-y-ocultacion-de-datos

Per exemple. La classe home

  • No permet accés a l'atribut edat (private)
  • Qualsevol que interactuï amb objectes "Home",
    • Desconeix l'existència de l'atribut "edat" o el mètode "arrodonirEdat"
    • Només pot usar mètodes de la seva interface. La seva interface són les operacions públiques

És interessant veure que si en algun moment es decideix modificar el càlcul que es realitza per establir l'edat dels objectes "Home", això no afectaria a cap de les entitats externes que en fan ús (Ni aparició d'errors, ni modificar codi, ni recompilar, etc...)

public class Home {

    private int edat;

    public Home(int edat) {
        super();
        this.edat = arrodonirEdat(edat);
    }

    public int getEdat() {
        return edat;
    }

    public void setEdat(int edat) {
        this.edat = arrodonirEdat(edat);
    }
   
    private int arrodonirEdat(int edat) {
        return ((int) edat/10)*10;
    }
}

Composició. Associació de classes

La composició de classes fa referència a usar instàncies de classes (objectes) dins altres objectes.

package dam.m3.uf4;

public class Punt {
    private int x;
    private int y;
   
    public Punt(int x, int y) {
        super();
        this.x = x;
        this.y = y;
    }
    public int getX() {
        return x;
    }
    public void setX(int x) {
        this.x = x;
    }
    public int getY() {
        return y;
    }
    public void setY(int y) {
        this.y = y;
    }
}
package dam.m3.uf4;

public class Cercle {
    private Punt centre;
    private int radi;
   
    public Punt getCentre() {
        return centre;
    }
    public void setCentre(Punt centre) {
        this.centre = centre;
    }
    public int getRadi() {
        return radi;
    }
    public void setRadi(int radi) {
        this.radi = radi;
    }
}


La representació de la composició (En UML s'anomena associació)

Associacio.png


El tractament d'atributs amb multiplicitat 1 (unaris) d'altres classes és igual que els atributs de tipus primitius.

La principal complicació és la gestió de la inicialització, cal recordar que mentre un objecte no s'instància té un valor null i l'accés a les seves propietats genera error en temps d'execució.


    /* Aquest constructor, deixa la responsabilitat de l'objecte
     * centre a la entitat externa que instància el Cercle.
     *
     * Cercle c1 = new Cercle(new Punt(2,4), 10)
     * Cercle c2 = new Cercle(null, 10)
     */
    public Cercle(Punt centre, int radi) {
        this.centre = centre;
        this.radi = radi;
    }

    /* Aquest constructor pren tota la responsabilitat i obliga
     * a la entitat externa a proporcionar tota la informació necessària.
     *
     * Cercle c1 = new Cercle(new Punt(2,4), 10)
     * Cercle c2 = new Cercle(null, 10)
     */
    public Cercle(int x, int y, int radi) {
        this.centre = new Punt(x,y);
        this.radi = radi;
    }
   
    /* Aquest constructor sempre inicialitza centre = null
     *
     * Cercle c3 = new Cercle(10)
     */
    public Cercle(int radi) {
        this.radi = radi;
    }


Multiplicitat

En general la composició pot implicar una relació 1:molts entre dues classes

Seguint amb l'exemple anterior podem pensar un classes "Quadrat", "Triangle", "Elipse", cadascuna d'aquestes la defineixen varis punts.

public class Triangle {
    private Punt[] vertex;

    // Responsabilitat externa vector mida 3. Arriscat 
    public Triangle(Punt[] vertex) { 
        this.vertex = vertex;
    }
   
    public Triangle() { 
        this.vertex = new Punt[3];
    }

    public Punt[] getVertex() {
        return vertex;
    }

    // index entre 0 i 2
    public void setVertex(Punt vertex, int index) {
        this.vertex[index] = vertex;
    }
}


Aquesta situació es pot generalitzar a un nombre indeterminat en la multiplicitat, per exemple els carrers d'una ciutat, els alumnes d'una classe.


public class Poligon {
    private static final int MAX = 10;
    private int top;
    private Punt[] punts;

    public Poligon() {
        super();
        this.punts = new Punt[MAX];
        this.top = 0;
    }
   
    // Afegir al final. Vigilar top >= this.punts.length
    public void addPunt(Punt punt) {
        this.punts[top] = punt;
        this.top++;
    }
   
    public Punt getPunt(int index) {
        return this.punts[index];
    }
}

Normalment els getters i setters sobre estructures de dades canvien, per exemple

  • setter : Operacions add i remove
  • getter : Afinar per accedir a un element: primer, últim, a través d'un índex

L'exemple anterior té un problema molt evident. El nombre de punts del polígon està limitat.


En aquests tipus d'associacions on la multiplicitat és indeterminada cal usar estructures de dades avançades, que poden tenir una mida variable (Col·leccions: piles, llistes, cues, bosses, mapes, etc...).

Què passa per exemple amb una associació "Alumne-Professor"?

  • Un alumne pot tenir varis professors
  • Un professor pot tenir varis alumnes

Tipus de composició. UML associació, composició i agregació

(Tenir en compte que aquests conceptes són més aviat referents al model, o sigui al problema i als seus requeriments, i no impliquen en el moment de la implementació de les relacions de composició)

En les relacions d'associació els objectes es relacionen entre ells en igualtat. Cadascun pot existir amb independència de l'altre (Exemple "professor - alumne")

Existeixen unes altres relacions de Tot - part

  • Agregació. Els objectes poden existir amb independència, però uns formen part dels altres obligatòriament. Exemple "Compte - Client". Un compte bancari sempre ha d'estar associat a un client. Si el compte desapareix no necessàriament ho ha de fer el Client
  • Composició (No confondre amb el concepte de composició genèric anterior). En aquest cas la relació de pertinença és més forta un l'existència d'un dels objectes està supeditada a l'altre. Exemple "Camí - Tram".


http://www.dcc.uchile.cl/~psalinas/uml/modelo.html

Herència

La Herència consisteix en organitzar es classes en una jerarquia (Pare – Fill). De manera que els descendents poden heretar característiques i comportaments del seus pares.

Es tracta d'una relació generalització - especialització.

En aquesta estructura la classe pare s’anomena superclasse i la classe filla subclasse.

Herencia.png


A l'exemple tant Alumne com Professor hereten els atributs de la Persona, per tant tenen dni, nom i edat. També heretarien mètodes si el pare en tingués.

A més existeixen diferents tipus d’herència en funció del nombre d’ascendents (Pares) que pot tenir una classe.

  • Herència simple : Cada classe només pot tenir una superclasse.
  • Herència múltiple: Una mateixa classe pot tenir vàries superclasses, i heretar de cadascuna d’elles.


Herencia2.png


L’herència també es pot classificar en funció del comportament dels seus descendents

  • Depenent si els objectes de la superclasse s’inclouen o no en una de les subclasses
    • Complete: Tot objecte d’una superclasse pertany a una de les subclasses
    • Incomplete: Un objecte d’una superclasse pot no pertànyer a una de les subclasses
  • Depenent si els objectes de la superclasse poden pertànyer alhora a vàries subclasses
    • Disjoint: Un objecte d’una superclasse només pot pertànyer a una de les subclasses
    • Overlapping: Un objecte d’una superclasse pot pertànyer a vàries de les subclasses

Tota jerarquia és una combinació d’un dels dos tipus

Per exemple

Herencia3.png

Polimorfisme. Sobreescriptura