Polimorfisme ad hoc

De Viquipèdia
Salta a: navegació, cerca

Descripció[modifica | modifica el codi]

En els llenguatges de programació, un polimorfisme ad hoc[1] és un tipus de polimorfisme en el qual les funcions polimòrfiques es poden aplicar a diferents tipus d'arguments. Una funció polimòrfica pot tenir diversos implementacions diferents i potencialment heterogenis depenent del tipus d'arguments als quals s'aplica. En el polimorfisme ad-hoc cal que s’especifiqui quins tipus de dades es poden usar. Això està en contrast amb el polimorfisme paramètric (també anomenat genericitat), en el qual les funcions polimòrfiques s'escriuen sense la menció de qualsevol tipus específic, i per tant pot aplicar una única implementació abstracta a qualsevol nombre de tipus d'una manera transparent. Aquesta classificació va ser introduïda per Christopher Strachey en 1967.

El polimorfisme ad-hoc s’aconsegueix gràcies al: subtipatge, sobreescriptura i sobrecàrrega de mètodes i lligam dinàmic missatge-mètode.

Subtipatge[modifica | modifica el codi]

Forma de polimorfisme en què un determinat tipus de dades (subtipus) està relacionat amb un altre tipus de dades (supertipus) per alguna noció de substituïbilitat. Típicament: si S és subtipus de T, aleshores qualsevol expressió (objecte) de tipus S pot ser usat amb seguretat en qualsevol context on s’esperi una expressió (objecte) de tipus T. Podem assignar (o passar com a paràmetre) un objecte de tipus S a una variable (paràmetre) declarada de tipus T sempre que S ≤ T.

Lligam estàtic missatge-mètode (early binding)[modifica | modifica el codi]

Polimorfisme ad hoc és un mecanisme d'enviament de missatges entre mètodes que delega el control d'una funció especificada a diverses funcions que poden tenir especificacions diferents. La sobrecàrrega permet múltiples funcions que accepten diferents tipus de dades que es defineixin amb el mateix nom; el compilador o intèrpret crida automàticament la funció correcta. D'aquesta manera, una funció anomenada "adjuntar" podrà adjuntar llistes de nombres enters, llistes de cadenes, llistes de nombres reals, i així successivament i tot cridat "adjuntar". La funció "adjuntar" correcta seria cridada basant-se en el tipus de llistes que es volen agregar. Això difereix de polimorfisme paramètric, en el qual la funció necessitaria ser escrita de forma genèrica, per treballar amb qualsevol tipus de llista. Ús de sobrecàrrega, és possible tenir una funció que fa dues coses completament diferents basades en el tipus d'entrada que se li ha passat; això no és possible amb el polimorfisme paramètric. Una altra forma de veure-ho és que la sobrecàrrega d'un mètode no és identificada només pel seu nom, sinó per la combinació del seu nom i el número, ordre i tipus dels seus paràmetres.

Aquest tipus de polimorfisme és comú en els llenguatges de programació orientats a objectes, molts dels quals permeten que als operadors poden ser sobrecarregats d'una manera similar a les funcions (vegeu la sobrecàrrega d'operadors). Alguns idiomes que no són dinàmics i no tenen polimorfisme ad hoc (incloent-hi classes de tipus) canvien l'ús d'operador amb mètodes que fan la mateixa funció amb noms més llargs com ara print_int, print_string, etc. Això pot ser vist com a avantatge (més descriptiu) o un desavantatge (excessivament prolix) depenent del punt de vista.

Un avantatge que de vegades es guanya a partir de la sobrecàrrega és l'aparició de l'especialització, per exemple, una funció amb el mateix nom es pot implementar de diverses maneres diferents, cadascun optimitzat per als tipus de dades particulars amb els que opera. Això pot proporcionar una interfície convenient per al codi que necessita ser especialitzat per a múltiples situacions per motius de rendiment. L'inconvenient és que el sistema de tipus no pot garantir la consistència de les diferents implementacions.

Lligam dinàmic missatge-mètode (late binding)[modifica | modifica el codi]

Hi ha altres formes en què el polimorfisme ad hoc es pot expressar. Per exemple en el llenguatge Smalltalk, la sobrecàrrega es realitza en temps d'execució, ja que els mètodes ("implementacions de la funció") per a cada missatge sobrecarregat ("funció sobrecarregada") es resolen quan estan a punt de ser executats. Això passa en temps d'execució, després que el programa es compila. Per tant, el polimorfisme en aquest cas s’aconsegueix utilitzant Subtipatge com en altres idiomes. Un cop d'ull més de prop també revelarà que Smalltalk proveeix una varietat lleugerament diferent del polimorfisme ad hoc. Perquè Smalltalk té un model d'execució amb lligam dinàmic,  que ofereix als objectes la capacitat de manejar missatges que no s'entenen, és possible seguir endavant i implementar la funcionalitat desitjada utilitzant polimorfisme sense fer servir sobrecarrega. Això pot ser una pràctica en general no recomanada per a la programació de tots els dies, però pot ser molt útil en l'aplicació de proxies. Si bé en termes generals fer servir mètodes de classe i la sobrecàrrega del constructor no es considera polimorfisme, hi ha llenguatges més uniformes en els quals les classes són objectes normals. En Smalltalk, per exemple, les classes són objectes normals. Això significa que els missatges enviats a les classes poden ser sobrecarregats, i també és possible crear objectes que es comporten com classes sense que les seves classes heretin de la jerarquia de classes. Aquestes són tècniques eficaces que es poden utilitzar per prendre avantatge de les potents capacitats de reflexió de Smalltalk. Acords similars també són possibles en llenguatges com Self i Newspeak.

Signatura d’un mètode[modifica | modifica el codi]

Nom del mètode més tipus, ordre i nombre de paràmetres. f(int,char) != g(int,char) != g(char,int) != g(char,int,int)

Sobreescriptura de mètodes[modifica | modifica el codi]

Substitució d’un mètode heretat per un altre amb idèntica signatura.

Sobrecàrrega de mètodes[modifica | modifica el codi]

Existència dins un mateix àmbit de visibilitat de mètodes amb el mateix nom i diferent signatura.

Sobrecàrrega d’operadors - Example[modifica | modifica el codi]

Es poden redefinir alguns dels operadors existents perquè actuïn d'una determinada manera, definida pel programador, amb els objectes d'una classe.

Imagineu-vos un operador + que pot usar-se en les següents maneres:

  1. 1 + 2 = 3
  2. 3.14 + 0.0015 = 3.1415
  3. 1 + 3.7 = 4.7
  4. [1, 2, 3] + [4, 5, 6] = [1, 2, 3, 4, 5, 6]
  5. [true, false] + [false, true] = [true, false, false, true]
  6. "bab" + "oon" = "baboon"

Per gestionar aquests sis crides a l'operador, es necessiten quatre diferents implementacions, o tres si les cadenes es consideren com a llistes de caràcters:

* En el primer cas s’ha d’invocar l'addició de nombres enters.

* En el segon i tercer casos s’ha d’invocar l'addició de números amb coma flotant (amb promoció o conversió de tipus, en el tercer cas).

* En el quart i el cinquè dels casos, la concatenació d'una llista ha de ser invocada.

* En l'últim cas s'ha d'invocar la concatenació de cadenes.

Així, el nom + realitat es refereix a tres o quatre funcions completament diferents. Aquest és un exemple de sobrecàrrega. (Tingueu en compte que els tipus de cadenes utilitzades en l'últim cas es presten mitjançant concatenació, en lloc d'addició, considerar "123" + "456", que es podria esperar que retorni "579 ". La sobrecàrrega pot per tant donar significat diferent a una operació, així com diferents implementacions.)

Referències[modifica | modifica el codi]

  1. C. Strachey, Fundamental concepts in programming languages. Lecture notes for International Summer School in Computer Programming, Copenhagen, August 1967