[go: up one dir, main page]

Classe (informàtica)

concepte de programació orientada a objectes

En programació orientada a objectes, una classe és una construcció d'un llenguatge de programació usada per agrupar camps relacionats i mètodes. Està conceptualment relacionat amb classes de la teoria de conjunts.

Una classe és un paquet cohesionat que consisteix en un tipus concret de metadada. Descriu les regles que marquen el comportament de l'objecte; les referències a aquests objectes són fetes com a instàncies d'una classe. Una classe té tant una interfície com una estructura. La interfície descriu com es pot interaccionar amb la classe i la instància a través de mètodes, mentre l'estructura descriu com es divideix la dada en camps dintre de la instància. Una classe és el tipus més específic d'un objecte en relació a una capa en concret. Una classe també pot tenir una representació (metaobjecte) en temps d'execució, que proveeix suport per manipular la metadada relativa a la classe.

Els llenguatges de programació que donen suport a les classes tenen diferències subtils en com donen suport a les diferents funcionalitats pròpies de les classes. La majoria donen suport a diferents formes d'herència. Molts llenguatges també donen suport a les funcionalitats que aporta l'encapsulació, per exemple, els especificadors d'accés.

Motius pels quals usar classes

modifica

Les classes quan es fan servir adequadament, poden accelerar el desenvolupament reduint la introducció de codi redundant, el testeig i la resolució de bugs. Si una classe ha estat testada en profunditat i se la considera com a robusta, la seva reutilització garanteix la no propagació d'errors arreu del codi. Si se'n fa una extensió, on se li afegeix nou codi, el mateix nivell de testeig de les noves parts de codi garanteixen el mateix nivell de fiabilitat de la classe resultant.

Una altra raó per fer servir classes és la de simplificar les relacions i les dades interrelacionades. Abans que escriure codi que crida repetidament la subrutina que dibuixa una finestra, és millor i més intuïtiu tractar la finestra com un objecte i dir-li que es redibuixi quan faci falta. Amb classes, els ítems GUI que són similars a finestres (per exemple, les caixes de diàleg), poden simplement heretar la majoria de les seves funcionalitats i estructures de dades de la classe de la finestra. El programador només necessita llavors afegir el codi propi de la nova classe. Efectivament, les GUIs són una possible aplicació de les classes molt comuna i molt útil i la programació GUI acostuma a ser molt més fàcil amb un bon disseny de classes.

Instanciació

modifica

Una classe és usada per crear-ne instàncies (objectes) per instaciar la classe. Les instàncies d'una classe comparteixen el mateix conjunt de propietats, encara que poden ser diferents en el seu contingut (poden tenir estats diferents). Per exemple, una classe "Persona" descriuria les propietats comunes a totes les instàncies de la classe Persona. Les persones són generalment semblants, però varien en certes propietats com l'alçada o l'amplada. La classe també definiria com es realitzen certes opcions: córrer, saltar, dormir, llençar un objecte, etc. Un dels beneficis de programar amb classes és que totes les instàncies d'una classe en particular seguirà el comportament definit de la classe que instacien.

En la majoria de llenguatges, les estructures, tal com estan definides per la classe, determinen com s'ocupa i allibera la memòria ocupada per les seves instàncies. Aquesta tècnica és coneguda com a model cookie-cutter. L'alternativa a aquest model és la que es fa servir, per exemple, al Python, on els objectes estan estructurats com contenidors clau-valor associatius. I aquests models, objectes que són instàncies de la mateixa classe podrien contenir diferents variables, de manera que l'estat pot ser dinàmicament afegit a l'objecte. Això es podria semblar en certes maneres, als llenguatges basats en prototipus, però no és equivalent.

Interfícies i mètodes

modifica

Els objectes defineixen la seva interacció amb el món exterior a través dels mètodes que exposen. Un mètode, és una subrutina (funció) amb una propietat especial que té el seu accés a dades emmagatzemades en un objecte (instància). Els mètodes que manipulen les dades de l'objecte i porten a terme tasques són, de vegades, tractades com a comportament.

Els mètodes formen la interfície dels objectes amb el món exterior; els botons del frontal d'un reproductor de vídeo, per exemple, són la interfície entre els humans i el material elèctric, que hi ha dintre de la caixa que forma l'electrodomèstic. Es prem el botó d'"on" per deixar l'aparell encès o apagat. En aquest exemple, la televisió és la instància, cada mètode és representat per un botó i el conjunt de botons comprèn la interfície. En la seva forma més comuna, una interfície és una especificació d'un grup de mètodes relacionats sense cap implementació associada dels mètodes.

Cada classe implementa una interfície, proveint d'estructura (és a dir, dada i estat) i implementacions de mètodes (és a dir, proveint de codi que especifica com funcionen els mètodes). Hi ha una distinció entre la definició d'una interfície i la implementació d'aquesta interfície. En la majoria de llenguatge, aquesta línia acostuma a ser difusa. Alguns llenguatge tanmateix, aporten característiques que ajuden a separar interfícies i implementació. Per exemple, una classe abstracta pot definir una interfície sense proveir d'implementació, mentre al llenguatge Dylan, les definicions de classe ni tan sols defineixen interfícies.

Les interfícies també poden ser definides per incloure un conjunt de funcions auxiliars, anomenades mètodes estàtics o mètodes de classe. Els mètodes estàtics, com mètodes d'instància, estan exclusivament associats amb la classe. La diferència amb els mètodes d'instància és que no treballen amb instàncies de la classe; així, els mètodes estàtics, ni requereixen una instància de la classe ni poden accedir a les dades de cap instància. Per exemple, donar la informació del fabricant d'un reproductor pot ser un mètode estàtic. Aquest mètode éstà clarament associat a la classe, encara que està fora del domini de cada instància individual de la classe.

Els llenguatges que suporten herència de classe també permeten a les classe que heretin interfícies de les classes de les que deriven. En llenguatges que suporten Classe (informàtica)#Amagar i encapsular encapsulació, es considera que la interfície d'una classe és el conjunt de mètodes i atributs públics que té (via mètodes getter i setter); se suposa que cap mètode privat o estructura interna de dades són coneguts per qui fa servir la classe i per tant no formen part de la interfície.

La metodologia de programació a objectes està dissenyada de manera que les operacions de qualsevol interfície d'una classe són fetes independents unes de les altres. Això ens aboca a disseny client-servidor (o per capes) on els servidors no depenen de cap manera dels clients. Una interfície no emplaça els clients a cap requeriment per invocar les operacions de la classe en cap ordre en particular. Aquesta tècnica té el benefici que el codi del client pot assumir d'una interfície estan disponibles per ser usades en qualsevol moment en què l'objecte apunta a una referència vàlida.

Estructura d'una classe

modifica

Donat que té una interfície, una classe conté una descripció d'estructura de dades emmagatzemades a les respectives instàncies de la classe. Les dades estan particionades en atributs (o camps, propietats membres de les dades). Tornant a l'exemple del televisor, les característiques visibles, com la mida i si suporta color, tots junts, conformen l'estructura. Una classe representa la descripció completa d'un televisor, incloent els seus atributs (estructura) i botons (interfície).

L'estat de les dades d'una instància està emmagatzemat en algun dispositiu, com la memòria o un fitxer. S'assumeix que l'emmagatzematge es troba en un lloc concret, on se'n pot accedir a la instància a través de referències a la identitat de les instàncies. Tanmateix, el lloc on es pot trobar en un moment donat, pot acabar variant. En aquests casos la identitat de l'objecte no canvia. L'estat està encapsulat i cada accés a l'estat es fa a través dels mètodes de la classe.

Una classe també descriu un conjunt d'invariants els quals són preservats per tots els seus mètodes. El propòsit principal dels invariants és establir. Un invariant és una restricció sobre l'estat d'una instància que ha de ser sempre satisfet. El principal propòsit dels invariants és dir quins objectes pertanyen a la classe. Un invariant distingeix tipus de dades i classes entre elles; això és, una classe no permet usar tots els possibles valors per l'estat de la instància i al seu lloc només permet els valors ben definits per la semàntica de l'ús pel qual el tipus de dades ha estat definit. Els mètodes (públics) suportats sovint estableixen una invariant de forma implícita. Alguns llenguatges de programació suporten l'especificació d'invariants com a part de la definició de la classe i les forcen arreu del tipus. L'encapsulació de l'estat és necessària per ser capaç de forçar les invariants de la classe.

Alguns llenguatges permeten que la implementació de la classe especifiqui mètode constructor i destructor i permeten crear i destruir objectes de la classe. Un constructor que admet paràmetres pot ser usat per crear objectes amb dades. El propòsit principal d'un constructor és el d'establir la invariant de la classe, generant un error si l'invariant no és vàlid. El propòsit principal d'un destructor és el de destruir la identitat de l'objecte, invalidant qualsevol referència cap a ella dintre del procés. En alguns llenguatges, un destructor pot retornar un valor que pot ser usat per obtenir un representació pública (codificació de transferència) d'un objecte d'una classe i simultàniament destruir la còpia de l'objecte emmagatzemat a la memòria de l'actual fil. Els constructors i els destructors també són, de vegades, usats per reservar i alliberar, respectivament, recursos associats amb l'objecte. De vegades, els constructors i destructors estan especificats com mètodes estàtics.

Una classe pot també contenir camps estàtics o camps de classe, que contenen dades que estan especificades respecte a la classe, tot i que a part de qualsevol instància. Si la classe en si mateixa és tractada com una instància d'una hipotètica metaclasse, els camps i mètodes estàtics serien camps i mètodes d'instància d'aquella metaclasse.

Representació d'una classe en temps d'execució

modifica

Com un tipus de dades, una classe acostuma a ser considerada com una construcció, en temps d'execució. Un llenguatge també pot suportar prototipus o metaobjectes factoria que representen informació en temps d'execució sobre classes o fins i tot representen metadades que proveeixen accés a funcionalitats de reflexió per manipular formats d'estructures de dades. Molts llenguatge distingeixen aquest tipus d'informació sobre classes des d'una classe sobre la base que la informació no té per què per què ser necessitada en temps d'execució. Alguns llenguatges dinàmics no fan distincions estrictes entre construccions en temps d'execució i de compilació tampoc no distingirien entre metaobjectes ni classes. Per exemple: si Humà és un metaobjecte que representa la classe Persona, les instàncies de Persona poden ser creades usant els recursos el metaobjecte humà.

Ocultació de la informació i encapsulació

modifica

Molts llenguatges suporten el concepte d'ocultació de la informació i encapsulació, típicament amb especificadors d'accés per membres de la classe. Els especificadors de la classe especifiquen restriccions a les quals s'hi accedirà a través d'instàncies. Alguns especificadors d'accés també controlarian com les classes hereden les restriccions. El seu primer propòsit és el de separar la interfície de la classe amb la seva implementació.

Un conjunt habitual d'especificadors d'accés (també anomenats modificadors) que suporten molts llenguatges orientats a objectes:

  • Privat: restringeix l'accés a la mateixa classe. Només els mètodes que són part de la mateixa classe poden accedir els membres privats.
  • Protected: permet que la mateixa classe i totes les subclasses hi accedeixin.
  • Public: vol dir que tots els clients poden accedir al membre pel seu nom.

Noteu que encara que molts llenguatges suporten aquests especificadors d'accés, la seva semàntica podria variar subtilment d'uns als altres.

Un ús habitual dels especificadors d'accés és el de separar les estructures internes de les dades d'una classe de la seva interfície; això vol dir que l'estructura interna és privada. Els mètodes d'accés públics poden ser usats per inspeccionar o alterar aquestes dades privades. Els diversos llenguatges de programació orientats a objectes forcen això a diversos graus. Per exemple, el llenguatge Java no permet que el codi del client accedeixi a les dades privades d'una classe en cap cas, mentre en llenguatges com Objective-C o Perl el codi del client pot fer el que vulgui. En C++, els mètodes privats són visibles però no accessibles a través de la interfície; tanmateix acostumen a ser fet invisibles per declarar explícitament classes plenament abstractes que representen les interfícies d'una classe.

Els especificadors d'accés no necessàriament controlen la visibilitat, en tant que fins i tot el mètodes privats poden ser visibles al codi del client. En alguns llenguatges, un membre inaccessible però visible pot ser referenciat en temps d'execució (per exemple, un apuntador cap a ell pot ser retornat per funcions seves), però tots els intents d'usar-lo referenciant el nom del membre des del client serien previnguts pel comprovador de tipus. El disseny orientat a objectes usa els especificadors d'accés en conjunció amb un disseny acurat d'implementació de mètodes publics per forçar invariants de les classes. Els especificadors d'accés han de protegir la classe contra usos accidentals dels membres des del client, però no són apters per proteccions en temps d'execució de dades d'objectes.

A més, alguns llenguatges, com ara C++, suporten mecanismes on una funció explícitament declarada com amic de la classe pot accedir als membres designats com privats o protegits.

De la mateixa manera, en Java, un mètode sense especificador d'accés pot ser accedit per les classes del mateix paquet.

Associacions entre classes

modifica

En disseny orientat a objectes i UML, una associació entre dues classes és un tipusd'enllaç entre els objectes corresponents. Una associació bidireccional entre classes A i B descriu una relació entre qualsevol instància de la classe A i alguns objectes de la classe B, i viceversa. Les associacions sovint són anomenades amb un verb, com podria ser "pertany a".

Un tipus de rol d'associació descriu el tipus de rol d'una instància d'una classe quan la instància participa en una associació. Un tipus de rol d'associació es relaciona amb l'altre extrem de l'associació. Un rol descriu una instància d'una classe des del punt de vista d'una situació a la qual la instància participa en l'associació. Els tipus de rol són col·leccions d'instàncies de rol agrupades per les seves propietats semblants. Per exemple, un rol de tipus "subscriptor" descriu la propietat comuna a instàncies de la classe "Persona" quan participen en una relació "se susbcriu a" amb la classe "Revista". També, una "Revista" té el tipus de rol "revista subscrita" quan els subscriptors s'hi subscriuen.

La multiplicitat en el rol de l'associació descriu quantes instàncies corresponen a cada instància de les altres classes de l'asscociació. Les multiplicitats habituals són: "0..1", "1..1", "1..*" i "0..*", on "*" vol dir qualsevol nombre d'instàncies.

Hi ha alguns tipus especials d'associacions entre classes.

Composició

modifica

La composició entre la classe A i la classe B descriu una relació de "part-de" on les instàncies de la classe B tenen un temps de vida més curt que les instàncies corresponents de la classe A. Hom diu que la classe B és part de la classe A. Això sovint és implementat en llenguatges de programació emmagatzemant les dades de la instància d'A de tal manera que ja contenen les dades de B.

L'agregació és una variant de la composició on les instàncies d'una classe són part d'instàncies de l'altra classe, però sense caler la restricció sobre el temps de vida més curt. La implementació de l'agregació es fa sovint mitjançant un Punter o referència a la intància continguda. En ambdós casos, les implementacions dels mètodes de les classes continents poden invocar mètodes de la classe continguda. Un exemple habitual de l'agregació és una llista. Que acabi el temps de vida d'una llista, no necessàriament implica que també acabi el temps de vida de la classe continguda.

Herència

modifica

Un altre tipus d'associació de classes és l'herència, que implica que les subclasses i superclasses, també conegudes respectivament com a fills (o classes derivades) i pares (o classes base). Si [cotxe] és una classe, llavors [gran turisme] i [furgó] són dues subclasses. Si [Botó] és una subclasse de [Control], vol dir que tots els botons són controls. Les subclasses sovint consisteixen en diversos tipus de modificacions (personalitzacions) a les seves classes respectives: addició de noves variables d'instància, addició de nous mètodes, i Sobrecàrrega dels existents per donar suport a les noves variables.

Conceptualment, una superclasse hauria de ser considerada com una part comuna de les seves subclasses. Aquest factor de compartició és un mecanisme per proveir reutilització. Així, estenent una superclasse fent modificacions de la classe existent, tendeix a estretir la seva aplicabilitat en diverses situacions. En disseny orientat a objectes, cal considerar un balanç acurat entre aplicabilitat i funcionalitat de superclasses. Les subclasses són diferents dels subtipus en el fet que el subtipus tracta el comportament comú, mente la subclasse se centra en l'estructura comuna.

Alguns llenguatges (com ara C++) permeten herència múltiple, de manera que una classe pot tenir més d'un pare. Aquesta tècnica rep crítiques per qui considera que implica una complexitat afegida innecessària i tècnicament és difícil d'implementar de manera eficient, encara que molts projectes es beneficiïn del seu ús. Java, per exemple, no ofereix herència múltiple, donat que els seus dissenyadors van tenir en compte la complexitat afegida. Al seu lloc, permet herència de múltiples classes abstractes (anomenades interfícies, en Java).

Sub i superclasses existeixen dintre d'una jerarquia definida per la relació d'herència. Si es permet l'herència múltiple, la jerarquia és un graf acíclic orientat, altrament, és un arbre. La jerarquia té classes al lloc dels nodes i les relacions d'herència com els enllaços. Els nivells de la jerarquia són capes o nivells d'abstracció. Les relacions són més pròpies de ser trobades entre classes del mateix nivell que entre classes de nivells diferents.

Hi ha dos punts de vista lleugerament diferents sobre si les subclasses de la mateixa classe han de ser disjuntes. De vegades, es considera que les subclasses d'una classe en particular han de ser completament disjuntes. Això vol dir que cada instància d'una classe té exactament una classe més derivada, que vol dir una subclasse de cada classe que té la instància. Aquesta visió no permet canvis dinàmics de la classe, ja que s'assumeix que els objectes es creen amb sobre una classe més derivada. La base per no permetre canvis a la classe és que es tracta d'un tipus definit en temps de compilació que no canvia en temps d'execució i el polimorfisme és usat per qualsevol canvi dinàmic en el comportament de l'objecte, de manera que aquesta funcionalitat no és necessària. El disseny que no necessita implementar canvis al tipus de l'objecte, serà més robust i fàcil de fer servir seguint aquesta visió.

L'altre punt de vista considera que les subclasses no tenen per què ser disjuntes. Llavors no hi ha concepte de classe més derivada i es considera que tots els tipus de la jerarquia d'herència són igualment tipus de la instància. Aquesta visió està basada en la classificació dinàmica dels objectes, com que una instància pot canviar de classe en temps d'execució. En aquest cas es diu que la classe de l'objecte és la seva estructura actual, tot i que els canvis hi són permesos. La base per permetre canvis a la classe de l'objecte és un inconvenient causat pel fet de reemplaçar una instància per una altra d'un tipus diferent, donat que caldria canviar totes les referències que inicialment apuntaven cap a la instància original per d'altres cap a la nova instància quan hi ha canvis a la classe. Aquesta anàlisi depèn de la proposició de què els canvis a l'estructura de l'objecte és habitual. Aquest cas es pot acabar donant o no, a la pràctica.

Llenguatges sense herència

modifica

Tot i que s'assumeix que els llenguatges basats en classes suporten herència, aquest no és un aspecte intrínsec al concepte de les classes. Hi ha llenguatges que suporten classes tot i que no suporten hernència, com ara les primeres versions de Visual Basic. Aquests llenguatges no aporten els beneficis estructurals de les interfícies de comprovació de tipus de manera estàtica. Això és causat perquè en llenguatges basats en objectes, és possible usar i estendre estructures de dades i afegir-hi mètodes en temps d'execució. Això prevé el compilador o intèrpret de ser capaç de comprovar el tipus d'informació especificat al codi font, ja que el tipus és construït dinàmicament i no definit de manera estàtica.

Categories de classes

modifica

Hi ha moltes categories de classes que depenen de modificadors. Noteu que aquestes categories no necessàriament categoritzen classes en particions diferents. Per exemple, mentre és impossible tenir una classe que és tant abstracta com concreta, una classe instanciada és implícitament una classe concreta i podria ser que una part d'ella estès definida en una classe abstracta.

Classe concreta

modifica

Una classe concreta és una classe que pot ser instanciada. Això contrasta amb classes abstractes, tal com es descriu a sota.

Classe abstracta

modifica

Una classe abstracta o classe base abstracta, és una classe que no pot ser instanciada. Una classe així només pot tenir significat si el llenguatge suporta herència. Una classe abstracta només és dissenyada com una classe pare de qui les classes filles podenser derivades. Les classes abstractes són usades sovint per representar conceptes abstractes o entitats. Aquestes característiques incompletes de la classe abstracta són llavors compartides per un grup de subclasses que afegeixen diferents variacions de les parts que manquen.

Les classes abstractes són superclasses que contenen mètodes abstractes i són definides de manera que les subclasses concretes les han d'estendre implementant els seus mètodes. Els comportaments definits per una classe com aquesta són genèrics i romandrà sense definir o sense implementar. Abans que una classe derivada d'una classe abstracta, com ara, una classe que pot ser instanciada, ha d'implementar mètodes particulars per tots els mètodes abstractes de les classe pare.

Quan especifiquem una classe abstracta, el programador es refereix a una classe que té elements que se suposa que han de ser implementats per herència. L'abstracció dels mètodes de la classe que han de ser implementats per les subclasses, està pensada per simplificar el desenvolupament de les aplicacions. Això també permet que el programador se centri en la planificació i el disseny.

La majoria de llenguatges de programació orientada a objectes permet que el programador especifiqui quines classes es consideren abstractes i no permetran que aquestes siguin instanciades. Per exemple, en Java es fa servir la paraula marcada abstract per aquest propòsit. En C++, una classe abstracta és aquella que té almenys un mètode abstracte.

Alguns llenguatges, notablement Java, suporten de manera addicional una variant de les classes abstractes, anomenades interfícies. Aquestes contenen mètodes accessibles públicament. D'aquesta manera, estan estretament relacionades (però no equivalents) al concepte abstracte d'interfícies, descrit en aquest article.

Classes sealed

modifica

Alguns llenguatges també suporten les classes sealed (permeables), que no poden ser usades com classes base, de manera que no poden ser abstractes. Bàsicament es fan servir per evitar la derivació. Afegeixen un nivell addicional d'estrictesa en temps de compilació, milloren l'ús de la memòria i impulsen certes optimitzacions que milloren l'eficiència en temps d'execució.

Classes locals i imbricades

modifica

En alguns llenguatges, les classes poden ser declarades en àmbits a part del global. N'hi ha de diversos tipus. Un tipus habitual és una classe imbricada o inner que està definida dintre d'una altra classe. En implicar dues classes, podem dir que parlem d'una associació de classes. Els mètodes d'una classe inner poden accedir als mètodes estàtics de les que les allotgen. No és típic que una classe imbricada estigui associada a la classe allotjant. Segons el llenguatge, es pot o no referenciar a aquestes classes des de fora de les que les allotgen. Un concepte relacionat és el dels tipus inner (també tipus de dades inner, tipus imbricat) que és la generalització del concepte de les classes inner. C++ és un exemple de llenguatge que ofereix suport a classes i tipus inner (via declaracions typedef).

Un altre tipus és una classe local, que és una classe declarada a dintre d'un mètode. Això limita les referències al nom de classe a l'interior de l'àmbit al qual ha estat referenciada la classe. Depenent de les regles semàntiques de la classe, hi poden haver restriccions addicionals per les classes local, que no tenen les que no en són. Una d'habitual és que els mètodes de la classe local accedeixin a les variables del mètode que les allotja. Per exemple, en C++, a una classe local se li permet referenciar variables estàtiques declarades a dintre del mètode que les allotja, però poden accedir a les seves variables automàtiques.

Metaclasses

modifica

Les metaclasses són classes les instàncies de les quals són classes. Una metaclasse descriu una estructura comuna d'una col·lecció de classes. Una metaclasse pot implementar un patró de disseny o descriure una alternativa ràpida per tipus de classes particualrs. Les metaclasses també són usades per descriure entorns de treball.

En alguns llenguatges com Python, Ruby, Java i Smalltalk, una classe és també un objecte, de manera que cada classe és una instància d'una única metaclasse, construïda al llenguatge. Per exemple, en Objective-C, cada objecte i classe és una instància de NSObject. El Sistema d'objectes de Common Lisp proveeix protocols de metaobjecte] (MOPs) per implementar aquestes classes i metaclasses.

Classes parcials

modifica

Les classes parcials són classes que poden ser dividides en múltiples definicions (típicament sobre múltiples fitxers), fent més fàcil aclarir-se amb grans quantitats de codi. En temps de compilació acaben quedant agrupades, de manera que no hi ha diferència en el resultat final. Un exemple de l'ús de classes parcials és la separació de la lògica de la interfície d'usuari i el processament lògic. Un benefici primari de les classes parcials és el de permetre a diferents programadors treballar en diferents parts de la mateixa classe de forma simultània. També generen codi més fàcil d'interpretar.

Les classes parcials han estat funcionant a Smalltalk sota el nom d'Extensions de classes (Class Extensions) durant bastant temps. Amb l'arribada de l'entorn de treball .NET2, Microsoft va introduir les classes parcials, suportades tant per C# i Visual Basic 2005.

Programació a objectes no basada en classes

modifica

Per sorpresa de qui està acostumat a usar classes, aquestes no són l'única manera de porta a terme la programació orientada a objectes. Una altra manera és la programació basada en prototipus. Els llenguatges que suporten programació no basada en classes acostumen a estar dissenyats amb la idea d'adreçar el problema del fort aparellament entre implementacions i interfícies a causa de l'ús de classes. Per exemple, el llenguatge Self, basat en prototipus, fou dissenyat per mostrar que el rol d'una classe pot ser substituït usant un objecte encara existent que serveix com a prototipus d'un objecte nou i el resultat llenguatge resultant és tan expressiu com Smalltalk amb més generalització en la creació d'objectes.

Exemples

modifica

Exemple 1

modifica
#include <iostream>
#include <string>

using namespace std;
class Hola
{
 string que;

 public:
 Hola(const string& s)
 : que(s)
 {
 }

 void digues()
 {
 cout << "Hola " << que << "!" << endl;
 }
};

int main(int argc, char** argv)
{
 Hola hola_mon("món");
 hola_món.digues();

 return 0;
}

Aquest exemple mostra com definir una classe en C++ anomenada "Hola". Té un atribut de tipus string privat anomenat "que", i un mètode públic anomenat "digues".

Exemple 2

modifica
class ClasseAbstracta
{
public:
 virtual void MetodeVirtual() = 0;
};

class ClasseConcrete : public ClasseAbstracta
{
public:
 void MetodeVirtual()
 {
 //fes el que toqui
 }
};

Un objecte d'una classe ClasseAbstracta no pot ser creat perquè la funció MetodeVirtual no ha estat definida (el =0 és una sintaxi C++ per una funció virtual pura, una funció que ha de tenir una part d'una classe concreta que en derivi però que no està definida a la classe base abstraxcta. La classe ClasseConcreta és una classe concreta perquè les seves funcipns (en aquest cas, la seva funció)ha estat declarada i implementada.

Exemple 3

modifica
#include <string>
#include <iostream>

using namespace std;

class MissatgeInet
{
 string m_assumpte, m_a, m_de;

public:
 MissatgeInet (const string& assumpte,
 const string& a,
 const string& de) : m_assumpte(assumpte), m_a(a), m_de(de) { }
 string assumpte () const { return m_assumpte; }
 string a () const { return m_a; }
 string de () const { return m_de; }
 virtual void escriuA(ostream &out) 
 {
 out << "Assumpte: " << m_assumpte << endl;
 out << "A: " << m_de << endl;
 out << "A: " << m_a << endl;
 }
};

Exemple 1

modifica
public class Exemple1
{
 // Aquesta és una classe Java, de forma automàtica extè la classe objecte
 public static void main (String args[]) 
 {
 System.out.println("Hola món!");
 }
}

Aquest exemple mostra un simple hola món.

Exemple 2

modifica
public class Exemple2 extends Exemple1
{
 // Aquesta classe extè la classe creada a l'exemple 1.
 protected int dada;

 public Exemple2()
 {
 // Aquest és un cosntructor per la classe. No retorna cap tipus.
 dada = 1;
 }

 public int getDada()
 {
 return dada;
 }

 public void setDada(int d)
 {
 dada = d;
 }
}

Aquest exemple mostra una classe que té un constructor definit, una dada membre, un mètode accessor (getDada) i un mètode modificador (setDada) per un atribut dada. Extè la classe d'exemple anterior. Noteu que en Java, totes les classes estenen automàticament la classe Object. Això permet escriure codi genèric per gestionar objectes de qualsevol tipus.

Visual Basic .NET

modifica

Exemple 1

modifica
Class Hola
 Private que as String

 Sub New(ByVal s as String)
 what = s
 End Sub

 Sub Digues()
 MessageBox.Show("Hola " & que)
 End Sub
End Class

Sub Main()
 Dim h As New Hello("Foobar")
 h.Digues()
End Sub

Aquest exemple és un port de l'exemple C++ de dalt. Ens mostra com fer una classe anomenada Hola amb una propietat privada anomenada que. També ens mostra l'ús apropiat d'un constructor, i té un mètode públic anomenat Digues. També ens mostra com instanciar la classe i cridar el mètode Digues.

Exemple 1

modifica
<?php
class A {
 public function foo() {
 if (isset($this)) {
 echo '$this està definit (';
 echo get_class($this);
 echo ")\n";
 } else {
 echo "\$this no està definit.\n";
 }
 }
}
?>

Exemple 2

modifica
<?php
	class ObjecteDada
	{
		public function getTemps()
		{
			/** Per mode E_STRICT:
			 *
			 * date_default_timezone_set('CET');
			 */

			return(time());
		}

		public function getDada()
		{
			return(date('jS F, Y', $this->getTime());
		}
	}
?>

Exemple 1

modifica
using System;

public class Programa
{
 public static void Main(string[] args)
 {
 Console.WriteLine("Hola món!");
 }
}

Aquest exemple ens mostra un tradicional exemple "Hola món!" en el llenguatge C# de Microsoft's C. La classe Programa conté un mètode estàtic simple, Main(), que crida System.Console.WriteLine per escriure un text cap a la sortida estàndard.

Exemple 2

modifica
using System;

public class Hola
{
 private string que;

 public Hola(string s)
 {
 que = s;
 }

 public void Digues()
 {
 Console.WriteLine("Hola " + que + "!");
 }
}

public class Programa
{
 public static void Main(string[] args)
 {
 Hola holaMon = new Hola("món");
 holaMon.Digues(); // escriu "Hola món!" cap a la sortida estàndard
 }
}

Aquest és un altre port de l'exemple C++ de dalt. Una classe anomenada Hola és creada amb un constructor que pern un paràmetre string. Quan s'invoca el mètode Digues(), la instància de Hola escriurà "Hola {que}!" cap a la sortida estàndard. Noteu que el mètode Main() (punt d'entrada) pot ser trobat dintre mateix de la classe.

ActionScript

modifica

Exemple 1

modifica
class Cart {

 private var cart:Array;

 public function Cart() {
 this.cart = new Array();
 }

 public function addItem(id:Number, name:String):Void {
 this.cart.push([id, name]);
 }

 public function removeItemById(id:Number):Void {
 var ln:Number = this.cart.length;
 for (var i:Number = 0; i<ln; i++) {
 var curr:Array = this.cart[i];
 if (curr[0] == id) this.cart.splice(i, 1);
 }
 }

 public function removeItemByName(name:String):Void {
 var ln:Number = this.cart.length;
 for (var i:Number = 0; i<ln; i++) {
 var curr:Array = this.cart[i];
 if (curr[1] == name) this.cart.splice(i, 1);
 }
 }
}

Exemple 1

modifica
class Hola
 def self.hola
 string = "Hola món!"
 return string
 end
end

Una classe Ruby Hola, amb un mètode hola. Aquest mètode retorna la variable string, que és canviada a "Hola món!".

Exemple 1

modifica
class Hola:
 def __init__(self): 
 print "Hola món!"

Una classe Python Hola, que escriu "Hola Món!" durant la seva creació.

Bibliografia

modifica
  • Allen J. Peralta Giménez, Horacio Rodríguez Hontoria : "Enginyeria del software : programació orientada a objectes; Allen J. Peralta Giménez, Horacio Rodríguez Hontoria". ISBN 84-7653-374-8
  • Meyer, B.: "Object-oriented software construction", 2a edició, Prentice Hall, 1997, ISBN 0-13-629155-4
  • Rumbaugh i al.: "Object-oriented modeling and design", Prentice Hall, 1991, ISBN 0-13-630054-5