Diferència entre revisions de la pàgina «DAM-M3-UF4. Conceptes d'Orientació a Objectes»
(→Herència) |
(→Herència) |
||
Línia 343: | Línia 343: | ||
} | } | ||
</pre> | </pre> | ||
+ | |||
+ | |||
+ | ==== Càsting ==== | ||
+ | |||
+ | Una altra de les conseqüències de l’herència és la determinació del tipus dels objectes d’una determinada classe. | ||
+ | |||
+ | Un objecte pertany alhora a les classes superiors de la jerarquia, i es pot comportar com a tal. | ||
+ | |||
+ | A l’exemple un Alumne en certes circumstàncies també es pot comportar com una persona. | ||
+ | |||
+ | [[file: herencia.png]] | ||
+ | |||
+ | |||
+ | |||
+ | ==== Classes Abstractes ==== | ||
+ | |||
+ | |||
+ | Una classe abstracte, no està completa, algun dels seus mètodes no està implementat, per tant no es pot instanciar, o sigui no es poden crear objectes d’aquesta. | ||
+ | |||
+ | Estableixen una descripció general de quelcom que s’ha d’acabar de concretar, cal definir alguna subclasse que implementi tots els seus mètodes i la completi. | ||
+ | |||
+ | |||
+ | ==== Intefaces ==== | ||
+ | |||
+ | Una interface és una classe abstracte on tots els seus mètodes són abstractes. | ||
+ | |||
+ | |||
+ | Les interfaces permeten simular a Java la herència múltiple. | ||
=== Polimorfisme. Sobreescriptura === | === Polimorfisme. Sobreescriptura === |
Revisió del 10:36, 6 set 2012
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ó)
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.
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.
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
El sistema d'herència a Java té les següents característiques
- Només admet herència simple. Tot i que existeixen mecanismes per simular la herència múltiple (interfaces).
- Totes les classes deriven de la classe Object. Aquesta herència està implícita i no cal indicar-la.
==> Això implica que qualsevol classe disposa dels mètodes de la classe Object que es poden consultar a l'API http://docs.oracle.com/javase/6/docs/api/
- Per crear una jerarquia de classes cal indicar-ho en la definició de la classe amb la paraula extends.
- Els constructors no s'hereten, per crear un objecte ha d'estar clara la classe a la qual pertany sense ambigüitats.
this, super
A vegades es poden produir confusions alhora d’usar atributs o mètodes, així es poden fer servir les següents paraules clau
- this fa referència a atributs o mètodes de l’objecte actual.
- super fa referència a atributs o mètodes de l’objecte del pare.
En general serà necessari cridar al constructor de la superclasse dins els constructor de la classe que hereta, per això es pot fer servir la crida a la sentència super(paràmetres), i ha de ser la primera línia del constructor.
Això és recomanable per garantir que la part del comportament de l'objecte responsabilitat del pare està correctament inicialitzada.
public class Clase { private int i; public Clase() { i = 10; // referència l’atribut i } public Clase( int i ) { this.i = i; /* s’utilitza this per evitar confusion entre l’atribut d’instància i el paràemtre */ } }
public class Clase { protected int i; public Clase( int i ) { this.i = i; } } public class SubClase extends { private int e; public SubClase( int i, int e ) { super(i); this.e = e; } public metode( int i ) { super.i = i; } }
Càsting
Una altra de les conseqüències de l’herència és la determinació del tipus dels objectes d’una determinada classe.
Un objecte pertany alhora a les classes superiors de la jerarquia, i es pot comportar com a tal.
A l’exemple un Alumne en certes circumstàncies també es pot comportar com una persona.
Classes Abstractes
Una classe abstracte, no està completa, algun dels seus mètodes no està implementat, per tant no es pot instanciar, o sigui no es poden crear objectes d’aquesta.
Estableixen una descripció general de quelcom que s’ha d’acabar de concretar, cal definir alguna subclasse que implementi tots els seus mètodes i la completi.
Intefaces
Una interface és una classe abstracte on tots els seus mètodes són abstractes.
Les interfaces permeten simular a Java la herència múltiple.
Polimorfisme. Sobreescriptura
Convencions / Bones pràctiques
S’utilitzaran les següents convencions:
- Els atributs sense herència es declararan private
- Els atribut que seran heretats i accessibles en alguna subclasse es declararan protected
- Hi haurà un mètode constructor que inicialitzarà tots els atributs d’instància.
- Hi haurà un mètode consultor públic per cada atribut amb el nom getNomAtribut()
- Hi haurà un mètode modificador públic per cada atribut amb el nom setNomAtribut(tipus NomAtribut)
- Els mètodes que no volem fer servir fora de la classe es declararan private