Professional Documents
Culture Documents
A la lliçó anterior, varem veure els objectes, i una forma de relació entre objectes
anomenada composició. Aquesta relació es defineix pensant per exemple en que
l’objecte casa té una taulada, i per tant hi ha una relació de composició entre els objectes
casa i taulada ( que es un objecte de la classe Triangle). La pregunta que responen és si
un objecte té un altre objecte.
En POO hi ha un altre tipus de relació que es diu d’herència. Per exemple, rectangle,
quadrat, triangle, son figures geomètriques. Per tant podem pensar en la classe figura
com la classe mare de totes les demes classes. Aleshores, les classes quadrat, rectangle,
triangle són filles de la classe mare Figura. Pel fet de ser filles, hereten les seves
propietats, mètodes i atributs, i poden accedir a ells a través de les propietats heretades.
La idea darrera d’això és que la classe mare contingui tots els atributs comuns a les
classes filles, mentre que les classes filles, tinguin els atributs específics de cada classe,
això es coneix com especialització, les classes filles són especialitzacions de la classe
mare.
Nosaltres podem definir mètodes a la classe mare, i després re definir-los a les classes
filles, per exemple en la classe Figura podem tenir un mètode Mostrar. Aquest mètode
no sap quina figura ha de dibuixar, per tant el deixem en blanc. Ara bé , a les classes
filles, Triangle, Rectangle, quadrat, podem re definir aquest mètode de manera que com
ja sabem quina figura s’ha de mostrar, podem posar el codi. Aquest procés se’n diu
Sobre escriptura del mètode ( Overriding). El mètode Mostrar de la classe mare (
Figura en aquest cas) es declara virtual, i a les classes filles ( Triangle, Rectangle,
Quadrat), el mètode Mostrar es declara override
En C#, totes les classes que fem i les del propi C#, hereten
d’una última classe, la classe Object que és la classe
mare de totes les classes. Aquesta classe té uns quants
mètodes virtual, i per tant els podem fer servir per
adaptar-los a la nostra classe particular.
El mètode més habitual per sobreescriure és el mètode ToString () que és una funció
que ens retorna una representació en forma de cadena del objecte. Per exemple en la
classe Persona amb atributs nom i DNI, el mètode ToString ens retornaria la cadena
formada pel nom i el DNI amb el format adient, per exemple
}
Una cosa a tenir present, és que en els constructors d’una classe derivada ( que hereta)
d’una classe base, la primera cosa que ha de cridar el constructor de la classe base a
través de base() Això és lògic, ja que al crear una classe filla( quan es crida el seu
constructor) primer s’han de crear les parts comunes ( que formen la classe mare) i
després les parts especifiques de cada classe.
Farem un exemple, semblant al de la casa, ara però, pensarem en l’objecte figura, com
classe mare de les classes, rectangle,i triangle. Les dos classes filles, tenen dos atributs
comuns, l’altura, i el color que ferm servir per dibuixar-les. Per tant, podem pensar que
la classe figura, tindrà dos atributs _altura i _color. A més, volem que totes les classes
filles es puguin mostrar ( dibuixar) per això declarem un mètode virtual void
Mostrar() que tindrà codi per posar el color de lletra al que haguem triat. A les
classes filles, (Rectangle, Triangle) aquest mètode tindrà el codi adient per mostrar un
rectangle o un triangle).
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace figures
{
// figura es la classe base, que conté la informacio comuna
a rectangle i triangle
public class Figura
{
private int _altura;// altura i color son atributs
comuns tant a rectangle com a triangle
private ConsoleColor _color;
public int Altura // propietat Altura
{
set { _altura = value; }
get { return _altura; }
}
public ConsoleColor Color // propietat Color
{
get { return _color; }
set { _color = value; }
}
public Figura() // constructor per defecte
{
this.Altura= 1;
this.Color = ConsoleColor.Red;
}
public Figura(int xalt) // constructor amb un argument,
el color per defecte es vermell
{
this.Altura = xalt;
this.Color = ConsoleColor.Red;
}
public Figura(int xalt, ConsoleColor xcolor) //
constructor amb 2 arguments
{
this.Altura = xalt;
this.Color = xcolor;
}
public virtual void mostrar()
{
// aquest metode nomes fa la feina comuna ( posa el
color de lletra
// al color triat), despres, quan estiguem a
Triangle
// el metode Mostrar de triangle fara la feina
especifica
Console.ForegroundColor = this.Color;
}
}
}
Ara hem de construir les classes filles, triangle, i rectangle, que han d’heretar de la
classe mare, això ho fem posant DOS PUNTS I EL NOM DE LA CLASSE MARE, en
aquest cas Figura
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace figures
{// aqui indiquem que Triangle es filla de Figura ( els :
indican això)
{
for (c = 1; c <= this.Altura - f; c++)
Console.Write(" ");
// canviem de color per pintar els asteriscs
for (c = 1; c <= 2 * f - 1; c++)
Console.Write("*");
Console.WriteLine();// saltem de linea
}
// tornem a posar el color Antic
Console.ForegroundColor = colorAntic;
}
}
}
Aquí veiem que els constructors, ( hi hem posat 3) tres criden a base() amb un valor, o
dos valors, això es fa per crear a través de base() la part comuna, i després afegir la part
específica ( en el cas del triangle no hi ha)
namespace figures
{/* la classe Rectangle hereda de figura, per tant
* tindra una altura, i un color, només afegim
* un nou atribut, labase (per no confondre amb base que es una
paraula reservada
* del C# per referir-se a la classe mare)
*/
public class Rectangle:Figura
{
private int _labase;// atribut nou, per indicar quan
mesura la base del rectangle
public int LaBase // propietat
{
get { return _labase; }
set { _labase = value; }
}
public Rectangle():base(1,ConsoleColor.Red)
{
// base crea la part comuna, altura i color
this.LaBase = 1; // nomes ens cal posar el valor de
la base
}
public Rectangle(int xb, int
xa):base(xa,ConsoleColor.Red)
{
// si cridem aquest constructor tindrem un rectangle
vermell ( per defecte)
// amb base xb i altura xa
this.LaBase = xb;
}
Ara farem servir les classes que hem creat a un programa però traurem profit del
polimorfisme, ja que crearem un vector de figures i després decidirem quines figures
creem,
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace figures
{
class Program
{
static void Main(string[] args)
{
Aquí, creem un vector f[] de figures, igual que si fos un vector d’integers i després
inicialitzem cada element a una figura diferent, podem mostrar tot en un bucle for, que
recorre el vector f[] mostrant cada element. Això és una aplicació del polimorfisme,
totes les classes filles són figures, per tant si creem f[] com un vector de figures, després
podem decidir ( mentre s’executa el programa) quines són les figures que realment
volem mostrar per fer la casa. Aquest concepte és molt important i fa que els programes
siguin més generals. Si ara volguéssim introduir un nou objecte, per exemple cercle
podríem fer que heretes de la classe figura i amb això ja el podríem incloure al
programa principal, nomes posant el codi del nou objecte
NOTA:Fixeu-vos que en molts llocs hem fet servir this, això és una referència al propi
objecte, per tant si hem de treballar amb dades del propi objecte, farem servir this per
referir-nos amb ell. Per exemple, la classe triangle, quan ha d’accedir a la seva propietat
Altura ho pot fer amb
this.Altura
This és una referència ( un punter en C++) que apunta al propi objecte. De vegades ens
pot ser útil per exemple en el problema de sumar fraccions, trobar la distancia entre dos
punts etc. Imaginem una classe punt amb dos valors enters per la X i per la Y i un
mètode esIgualA que rep com a argument un altre punt. Declarem al programa
principal p1 i p2 com a punts. Si volem saber si p1 es igual a p2 farem
bool res=p1.esIgualA(p2);
a dintre del mètode esIgualA hem de accedir als valors X,Y del primer punt per fer-ho,
cal fer servir this ( que apunta al objecte que crida el mètode, en aquest cas p1)