Programació orientada a objectes

De la Viquipèdia, l'enciclopèdia lliure.
Saltar a la navegació Saltar a la cerca

En informàtica , la programació orientada a objectes (en anglès object-oriented programming, en acrònim OOP) és un paradigma de programació que permet definir programes d’ objectes capaços d’interactuar entre ells mitjançant l’intercanvi de missatges. Particularment adequat en contextos en què es poden definir relacions d’interdependència entre els conceptes a modelar (contenció, ús, especialització), una àrea que més que d’altres aconsegueix explotar els avantatges de la programació orientada a objectes és la de les interfícies gràfiques .

Altres avantatges de la programació orientada a objectes inclouen:

  • proporciona un suport natural al modelatge de programari d'objectes del món real o del model abstracte que es reproduirà;
  • permet una gestió i manteniment més fàcils de grans projectes;
  • l’organització del codi en forma de classes afavoreix la modularitat i la reutilització del codi .

Història

El concepte de classe es pot considerar l’hereu del tipus de dades abstractes , un concepte que es va desenvolupar inicialment dins del paradigma de la programació procedimental , que preveu la definició de tipus de dades amb els quals es pot interactuar només a través d’una interfície ben definida, amagant detalls de la implementació a l'usuari.
Les construccions sintàctiques que permeten definir una classe, en llenguatges orientats a objectes, es poden veure com un suport estructurat per crear dades abstractes.

El primer llenguatge de programació orientat a objectes va ser Simula ( 1967 ), seguit als anys setanta per Smalltalk i diverses extensions de Lisp . Als anys vuitanta, es van crear extensions orientades a objectes del llenguatge C ( C ++ , Objective-C i altres) i altres llenguatges ( Object Pascal ). A la dècada de 1990 es va convertir en el paradigma dominant, pel qual la majoria dels llenguatges de programació estaven orientats a objectes de forma nativa o tenien una extensió a aquest efecte. Els llenguatges que només admeten el paradigma de programació orientat a objectes són Smalltalk i Eiffel . Més sovint ens trobem amb una implementació no exclusiva del paradigma de programació orientada a objectes, com en C ++ , Java , Delphi , Python , C # , Visual Basic .NET , Perl , PHP (a partir de la versió 4).

Descripció

La programació orientada a objectes consisteix a agrupar en una àrea limitada del codi font (anomenada classe ), la declaració de les estructures de dades i els procediments que hi operen. Les classes, per tant, constitueixen models abstractes, que en temps d' execució són invocats per crear o crear objectes de programari relacionats amb la classe invocada. Aquests últims estan equipats amb atributs (dades) i mètodes (procediments) definits / declarats per les classes respectives.

La part del programa que fa ús d’un objecte s’anomena client .

Un llenguatge de programació està orientat a objectes quan permet implementar tres mecanismes utilitzant la sintaxi nativa del llenguatge [1] :

L'encapsulació consisteix a separar l'anomenada interfície d'una classe de la seva implementació corresponent, de manera que els clients d'un objecte d'aquesta classe puguin utilitzar la primera, però no la segona.

L’herència permet essencialment definir classes a partir d’altres ja definides.

El polimorfisme permet escriure un client que pugui utilitzar objectes de diferents classes, però amb la mateixa interfície comuna; en temps d'execució, aquest client desencadenarà diferents comportaments sense conèixer a priori el tipus específic de l'objecte que se li passa.

Classes

Icona de la lupa mgx2.svg El mateix tema en detall: Classroom (informàtica) .

Les classes defineixen tipus de dades i permeten la creació d'objectes segons les característiques definides a la mateixa classe. Gràcies a les relacions d' herència , és possible crear classes noves a partir de les existents, ampliant-les amb característiques addicionals.

La classe consta de:

  • atributs (anàlegs als membres d’un registre ), és a dir, de les variables i / o constants que defineixen les característiques o propietats dels objectes que es poden instanciar invocant la classe; els valors inicialitzats dels atributs s’obtenen mitjançant l’anomenat constructor ;
  • mètodes , és a dir, procediments que operen sobre atributs.

Una comparació (imprecisa) amb les matemàtiques és la següent: es pot pensar que una classe defineix un conjunt d’una manera intensiva, és a dir, que indica les seves característiques en lloc d’enumerar els seus elements i que els objectes són els elements d’aquest conjunt. Tanmateix, en matemàtiques, el nombre d’elements és una característica intrínseca del mateix conjunt i es defineix quan es defineix el conjunt, mentre que en la programació és possible instanciar una classe un nombre arbitrari de vegades (teòricament, de zero a infinit; a la pràctica, des de zero fins que s’esgota la memòria de l’ordinador) i que depèn de l’execució del programa. Per aquest motiu, és preferible considerar la classe com un model abstracte instantani.

Dit d’una altra manera, una classe és comparable al projecte d’una infraestructura que després es pot posar en funcionament / operar o realitzar o no amb la instanciació dels seus objectes tots amb les mateixes característiques, o els atributs (amb valors diferents), sobre els quals funcionaran mètodes o funcions.

Objectes

Icona de la lupa mgx2.svg El mateix tema en detall: Objecte (informàtica) .

Un objecte és una instància d'una classe. Està equipat amb tots els atributs i mètodes definits per la classe i actua com a proveïdor de "missatges" (els mètodes) que el codi executable del programa (procediments o altres objectes) pot activar a petició.
Enviar un missatge a un objecte significa, en argot, invocar un mètode sobre aquest objecte. El mètode rep com a paràmetre (sovint implícit) l'objecte al qual es va invocar, que es pot fer referència a través d'una paraula clau o d'una sintaxi específica, fins i tot si es passa com a paràmetre implícit; per exemple, a C ++ , Java i C # this la paraula clau this ( $this a PHP), mentre que a Smalltalk , Objective-C , Python i Ruby self la paraula clau self .

Des del punt de vista de l'ordinador, cada objecte s'identifica mitjançant una àrea de memòria determinada, en la qual s'emmagatzemen els atributs , i el valor d'aquest últim determina l'estat intern de l'objecte. Instanciar un objecte significa assignar memòria i, finalment, inicialitzar-la segons les especificacions definides per la classe. Molts llenguatges proporcionen suport per a la inicialització automàtica d’un objecte, amb un o més mètodes especials, anomenats constructors . De la mateixa manera, el final de la vida d’un objecte es pot gestionar amb un mètode anomenat destructor .

El codi executable del programa accedeix a aquesta àrea de memòria sempre i només de la manera definida per la classe.
Segons el principi conegut com a ocultació d'informació , l'accés als camps d'un objecte només s'ha de permetre mitjançant mètodes invocats sobre aquest mateix objecte. L’avantatge principal és que el control complet sobre l’estat intern s’assigna a una àrea restringida del codi executable del programa (la classe), perquè el codi extern no està autoritzat a modificar-lo. En aquest cas, és possible imposar restriccions als possibles valors que l’atribut tupla pot assumir o no, i també a les possibles transicions entre aquests estats. Per tant, un objecte es pot veure com una màquina d'estats finits .

Encapsulació

Icona de la lupa mgx2.svg El mateix tema en detall: Encapsulació (informàtica) .

L'encapsulació és la propietat mitjançant la qual les dades que defineixen l'estat intern d'un objecte i els mètodes que defineixen la seva lògica són accessibles als mètodes de l'objecte mateix, mentre que no són visibles per als clients. Per alterar l'estat intern de l'objecte, cal invocar els seus mètodes públics, i aquest és el propòsit principal de l'encapsulació. De fet, si es gestiona correctament, us permet veure l'objecte com una caixa negra , és a dir, una "caixa negra" amb la qual la interacció només es produeix a través dels mètodes definits per la interfície. La qüestió és proporcionar als usuaris la funcionalitat ocultant els detalls relacionats amb la seva implementació. Un exemple podria ser un objecte "matemàtic" que entre les moltes operacions que proporciona és un que multiplica dos nombres. Per exemple, multiplica (2,3) retorna 6. Ara, l'algorisme de multiplicació pot ser un dels molts algorismes que hi ha, però això per a aquells que anomenen el mètode multiply () no té cap diferència. L’important és que el resultat no sigui erroni.

Herència

Icona de la lupa mgx2.svg El mateix tema en detall: Herència (informàtica) .

El mecanisme d’ herència s’utilitza en la fase d’estructuració / definició / planificació de programari o en extensions posteriors i permet derivar noves classes a partir de les ja definides, creant una jerarquia de classes. Una classe derivada a través de l’herència ( subclasse o classe secundària), manté els mètodes i atributs de les classes d’on deriva ( classes base , superclasses o classes pares); a més, pot definir els seus propis mètodes o atributs i redefinir el codi d'alguns dels mètodes heretats a través d'un mecanisme anomenat prioritari .

Quan una classe hereta d'una sola superclasse, es coneix com a herència única; viceversa, parlem d’herència múltiple. Alguns llenguatges (Java, Smalltalk entre d'altres) ofereixen un suport únic per a l'herència única. Altres (C ++, Python) també preveuen herències múltiples.

Alguns llenguatges mecanografiats (Java, C #) proporcionen l'herència d'interfícies, així com classes.

L'herència pot ser utilitzat com un mecanisme per aconseguir l'extensibilitat i la reutilització de codi, i és particularment avantatjosa quan s'usa per definir subtipus , explotant els is-a les relacions existents en la realitat que l'estructura de classes és un modelatge. A més de la reutilització evident del codi de superclasse, l’herència permet la definició de codi genèric a través del mecanisme del polimorfisme.

Exemple

Si ja hi ha una classe MezzoDiTrasporto al programa que té la propietat de les dades de posició, velocitat, destinació i càrrega útil i es requereix una nova classe Avió , és possible crear-la directament des de l’objecte MezzoDiTrasporto declarant una classe de l’ Avió. tipus que hereta de MezzoDiTrasporto i afegint també l'atribut que identifica l' altitud del creuer , amb l'avantatge que la nova classe adquirirà tots els membres definits a MezzoDiTrasporto pel fet de ser una subclasse.

Subtipatge

Icona de la lupa mgx2.svg El mateix tema en detall: Subtipus (informàtica) .

Tot i que conceptualment hi ha diferències molt marcades, el mecanisme d’herència entre classes ( subclassificació ), mitjançant el mecanisme del polimorfisme per inclusió, permet als llenguatges orientats a objectes modelar l’herència entre tipus ( subtipus ).

Segons el principi de substitució de Liskov , un tipus S és un subtipus de T quan és possible substituir totes les instàncies de T per instàncies de S mentre es manté intacte el programa.

Amb les precaucions adequades és possible crear una relació classe-subclassa que també respecti les restriccions de la relació tipus-subtipus. Des del punt de vista sintàctic, això requereix que tots els mètodes de la superclasse estiguin presents a la subclasse i que les seves respectives signatures siguin compatibles. En conseqüència, una subclasse que vulgui definir un subtipus pot redefinir els mètodes de la superclasse, però no els pot eliminar. La signatura del mètode només es pot modificar parcialment, respectant les restriccions a la variació dels paràmetres respecte a la cadena d'herència.

No obstant això, el compliment de restriccions sintàctiques no és suficient, per si sol, per garantir el compliment de la condició de Liskov: la redefinició de mètodes o la reassignar atributs [ poc clar ] , de fet, podria comprometre la compatibilitat amb el temps d'execució.

En molts idiomes, quan definiu una subclasse, podeu decidir suprimir o canviar les propietats d'accés d'un mètode heretat. En aquest cas, l'operació de subclasificació no coincideix amb l' operació de subescriptura . Alguns llenguatges orientats a objectes, en particular Sather , divideixen explícitament la subclassificació i el subtipus a nivell sintàctic.

En els llenguatges amb escriptura estàtica i explícita , el subtipatge s’admet mitjançant polimorfisme mitjançant la inclusió de subclasses: la mateixa variable pot referir-se a un objecte del tipus per al qual va ser declarada, o de tipus derivats. El tipus d'objecte identificat per la variable, per tant, es defineix en temps d' execució ( enllaç dinàmic ) i es pot canviar durant l'execució del programa.

Polimorfisme

Icona de la lupa mgx2.svg Mateix tema en detall: Polimorfisme (informàtica) .

En la programació orientada a objectes, el nom de polimorfisme per inclusió indica el fet que el mateix codi executable es pot utilitzar amb instàncies de classes diferents, amb una superclasse comuna.

Unió dinàmica o polimorfisme horitzontal

Icona de la lupa mgx2.svg El mateix tema en detall: Enquadernació .

El polimorfisme és particularment útil quan es tria la versió del mètode a executar en funció del tipus d’objecte realment contingut en una variable en temps d’ execució (en lloc de compilar-se ). Aquesta característica s’anomena enllaç dinàmic (o enllaç tardà) i està suportada pels llenguatges de programació orientats a objectes més populars.

Si una variable de tipus A té dos subtipus (subclasses) B i C , tots dos substitueixen el mètode m () , l’objecte contingut a la variable pot ser de tipus A , B o C i quan s’invoca el mètode m a la variable () executa la versió adequada per al tipus d'objecte que conté la variable en aquell moment.

Per tornar a l’exemple anterior, se suposa que un avió ha d’afrontar procediments d’arribada i sortida molt més complexos que els d’un camió normal, com és de fet: aleshores cal canviar els procediments d’ arribada () i sortida () en comparació amb els de la classe base MezzoDiTrasporto . Després es redefineixen a la classe Avió per tal d’obtenir el comportament necessari (polimorfisme): en aquest punt, de la llista de vehicles és possible agafar qualsevol mitjà i trucar a l’ arribada () o la sortida () sense haver de preocupar-se de què és l'objecte que esteu manipulant: ja sigui un vehicle normal o un avió, sempre es comportarà responent a la mateixa trucada de la manera correcta.

El suport per a la vinculació dinàmica no és necessàriament automàtic en tots els llenguatges de programació orientats a objectes. Per exemple, a Java, Smalltalk, Python, Ruby, l’enllaç dinàmic s’utilitza implícitament com a comportament predeterminat a les classes polimòrfiques, mentre que a C ++ s’activa inserint la paraula clau virtual a la signatura del mètode en qüestió.

El suport en temps d'execució d'una crida a mètode polimòrfic requereix que s'associï una variable polimòrfica a metadades implícites que continguin el tipus de dades contingudes a la variable en un moment determinat o la taula de funcions polimòrfiques.

Exemple: enquadernació dinàmica

Suposem que teniu el pseudocodi següent a Java, on Class2 és una subclasse de Class1 :

 mètode nul ( entrada int ) {
    Classe1 c ;
    
    si ( entrada > 0 )
        c = nova classe 1 ();
    en cas contrari
        c = nova classe 2 ();
    
    c . doSomethingImportant ();
}

Tingueu en compte que doSomethingOfImportant és un mètode definit per Class1, però potser s'ha redefinit a Class2 (perquè potser cal imprimir-lo de manera diferent). El compilador no pot saber en el moment de la compilació si hi ha un objecte associat a la classe Class1 o Class 2. Mitjançant l’enllaç dinàmic es farà l’elecció de quin mètode s’ha d’ enllaçar realment durant l’execució ( temps d’execució ), quan realment s’anomena el mètode.

Polimorfisme vertical

Amb l’expressió polimorfisme vertical entenem la possibilitat de redefinir o reutilitzar mètodes fins i tot en classes derivades.

Problemes dels llenguatges OOP

Alguns mecanismes inclosos en la gestió d'objectes provoquen despeses generals en termes de temps i memòria, que en determinades situacions poden provocar problemes d'eficiència.

Alguns llenguatges com Java i C ++ prefereixen un enfocament híbrid sobre l'OOP "pur", com el llenguatge Smalltalk , sempre que alguns tipus de dades primitius no es tractin com a objectes. Els avantatges d’aquest enfocament són particularment evidents en la presència de càlculs numèrics; d'altra banda, sempre que es necessita un objecte en lloc d'un tipus primitiu, cal recórrer a un embolcall especial i això pot comportar baixades de rendiment.

Aquest embolcall també pot ser proporcionat automàticament pel propi llenguatge, com en el cas de Java o C # , mitjançant una conversió automàtica anomenada "autoboxing". Permet posar valors de tipus primitius (per exemple, enters, caràcters) dins d’objectes i després cridar parts de codi que vulguin objectes sense escriure explícitament la instrucció de creació de l’objecte que inclou el valor. Aquest tipus de boxa resol el problema d’escriure un embolcall a mà, però, per descomptat, el rendiment es manté.

Altres crítiques a la POO es refereixen a la major complexitat estructural pel que fa als llenguatges procedimentals, davant les limitacions introduïdes per seguir el paradigma orientat a objectes. També hi ha algunes mancances conceptuals (sobretot pel que fa al subtipus), que les addicions a diferents implementacions en idiomes poden causar problemes al programador. Per exemple, l'operació en contextos polimòrfics no està garantida quan es redefineixen mètodes en una cadena d'herència. A més, canviar les definicions de les classes base pot provocar errors en cascada a les subclasses ( problema de classe base fràgil ).

Nota

  1. ^ Aquests mecanismes també es poden simular en llenguatges que no es consideren orientats a objectes, sempre que s'adoptin altres construccions i es respectin certes convencions a l'hora d'escriure el text del programa.

Bibliografia

Articles relacionats

Enllaços externs

Control de l'autoritat Thesaurus BNCF 57290 · LCCN (EN) sh87007503 · GND (DE) 4233947-9 · BNF (FR) cb12115131k (data) · BNE (ES) XX537453 (data) · NDL (EN, JA) 00.93798 milions
Informàtica Portal de TI : accediu a les entrades de Viquipèdia relacionades amb TI