Llenguatge de programació Eiffel
El llenguatge de programació Eiffel fou concebut el 1985 pel Dr. Bertrand Meyer, és un llenguatge orientat l'objecte pur, dissenyat per desenvolupar de manera eficient programari reutilitzable, extensible i fiable. Va sorgir del món acadèmic com a llenguatge de programació per a l'ensenyament, això pot justificar que la seva sintaxi estigui inspirada en la de Pascal. Avui dia Eiffel és un llenguatge estandarditzat per ISO, forma part dels llenguatges de programació suportats per Microsoft .NET, i està tenint força aplicació a la indústria. Com que el creador d'aquest llenguatge, el Dr. Bertrand Meyer, fou un pioner notable de la programació orientada a l'objecte, va concebre el llenguatge des de la seva visió del desenvolupament de programari i potser per això hi ha un reconeixement general que és el llenguatge de programació orientada a l'objecte més ben dissenyat i més complet. Molts dels conceptes introduïts en aquest llenguatge més tard han aparegut en altres llenguatges com Java o C#. CaracterístiquesLes característiques clau del llenguatge Eiffel inclouen:
Objectius de dissenyEiffel posa èmfasi a les sentències declaratives per sobre el codi de procediment i intenta eliminar la necessitat de les instruccions de gestió dinàmica de la memòria (bookkeeping en anglès). Eiffel defuig la codificació trucs o tècniques de codificació destinats a facilitar l'optimització al compilador. L'objectiu no és només per fer més llegible el codi, sinó també per permetre als programadors concentrar-se en els aspectes importants d'un programa sense perdre's en els detalls d'implementació. La simplicitat d'Eiffel està destinada a promoure solucions simples, extensibles i reutilitzables; i fiables als problemes informàtics. Els compiladors per programes d'ordinador escrits en Eiffel proporcionen tècniques extensives d'optimització, com ara la substitució automàtica d'una crida pel codi cridat (automatic in-lining en anglès), que alleugen al programador d'una part de la càrrega, mentre que l'optimització de codi produït és d'una eficiència comparable a la del codi escrit en C++. AntecedentsEiffel va ser desenvolupat originalment per Eiffel Software, una empresa originalment anomenada Interactive Software Engineering Inc (ISE), fundada per Bertrand Meyer. El llibre Object-Oriented Software Construction (Construcció de programari orientat a l'objecte) conté un tractament detallat dels conceptes i la teoria de la tecnologia d'objectes que han dut a dissenyar Eiffel.[1] L'objectiu de disseny del llenguatge Eiffel, les biblioteques (libraries en anglès), i els mètodes de programació és permetre als programadors crear mòduls fiables, de programari reutilitzable. Eiffel suporta herència múltiple, genericitat, polimorfisme, encapsulació, les conversions de tipus segur, i covariància dels paràmetres. La contribució més important d'Eiffel a l'enginyeria de programari és el disseny per contracte (DbC, en són sigles en anglès), en què les assercions, precondicions, postcondicions i els invariants de classe es fan servir per ajudar a garantir la correcció del programa sense sacrificar-ne l'eficiència. El disseny d'Eiffel es basa en la teoria de la programació orientada a l'objecte, amb només una influència menor d'altres paradigmes o qüestions pel suport del codi heretat. Eiffel formalment suporta tipus abstractes de dades. Sota el disseny d'Eiffel, un text de programari ha de ser capaç de reproduir la seva documentació de disseny del text en si, utilitzant una aplicació formal dels "Tipus Abstractes de Dades". Les implementacions i entornsEiffelStudio és un entorn de desenvolupament integrat (IDE, en són les sigles en anglès) disponible en virtut d'un codi obert o una llicència comercial. Ofereix un entorn orientat a l'objecte per a l'enginyeria del programari. EiffelEnvision és un plug-in per a Microsoft Visual Studio que permet als usuaris editar, compilar i depurar projectes Eiffel des del Microsoft Visual Studio IDE. EiffelStudio i EiffelEnvision són gratuïts per a ús no comercial. Hi ha unes altres quatre implementacions de codi obert: "The Eiffel Compiler" tecomp, Gobo Eiffel, SmartEiffel, -la implementació GNU, basada en una versió anterior de llenguatge- i Visual Eiffel. Diversos llenguatges de programació incorporen elements aportats per primera vegada a Eiffel. Sather, per exemple, es va basar originalment en Eiffel, però ha variat des de llavors, i ara inclou diverses característiques de programació funcional. El llenguatge interactiu d'ensenyament Blue, precursor de BlueJ, també està basat en Eiffel. L'Apple Media Tool inclou basat en Eiffel un Apple Media Language. Les especificacions i normesLa definició del llenguatge Eiffel és un estàndard internacional de l'ISO. L'estàndard va ser desenvolupat per ECMA International, que per primera vegada aprovada la norma, el 21 de juny de 2005, com a estàndard ECMA 367, Eiffel: Analysis, Design and Implementation Language. El juny de 2006, ECMA i ISO van aprovar la segona versió. El novembre de 2006, l'ISO va publicar per primera vegada aquesta versió. L'estàndard es pot trobar i utilitzar d'una manera gratuïta en el web de ECMA[2] La versió ISO[3] és idèntica en tots els aspectes excepte el format. Eiffel Software's, "tecomp: The Eiffel Compiler" i Eiffel-library-developer de Gobo s'han compromès a aplicar l'estàndard; Eiffel Software's EiffelStudio 6.1 and "tecomp: The Eiffel Compiler" implementen alguns dels principals nous mecanismes -en particular, els agents en línia, assignador d'ordres, notació parentitzada, herència no conforme, i els tipus annexats (attached-types en anglès). L'equip de SmartEiffel s'ha apartat d'aquest estàndard per crear la seva pròpia versió del llenguatge, que creuen que està més a prop de l'estil original d'Eiffel. Object Tools no ha revelat si en futures versions del seu compilador d'Eiffel complirà amb l'estàndard. L'estàndard cita els següents predecessors d'especificacions del llenguatge Eiffel:
La versió actual de l'estàndard de juny de 2006 conté algunes inconsistències (per exemple, les redefinicions de la covariància). El comitè de ECMA encara no ha anunciat cap calendari ni en quina direcció es resoldran aquestes inconsistències. La sintaxi i la semànticaEstructura generalUn "sistema" o "programa" Eiffel és una col·lecció de classes. Per sobre del nivell de les classes, Eiffel defineix el grup (cluster en anglès), que és essencialment un grup de classes, i possiblement de subgrups (grups niats). Les agrupacions no són una estructura de control sintàctica, sinó més aviat una convenció de l'organització estàndard. Normalment una aplicació Eiffel s'organitzarà amb cada classe en un arxiu separat, i cada grup en un directori o carpeta que conté els fitxers de les classes. En aquesta organització, els subgrups són subdirectoris. Per exemple, en virtut de les convencions estàndard de l'organització i l'entorn, Una classe conté característiques, que són similars als "membres", "atributs" o "mètodes" en altres llenguatges de programació orientats a l'objecte. Una classe també defineix els seus invariants, i conté altres propietats, com una secció de "notes" per a documentació i metadades. Els tipus estàndard de dades d'Eiffel, com Cada sistema ha de tenir una classe designada com "arrel" ("root" en anglès), amb un dels seus procediments de creació designat com a "procediment arrel". L'execució d'un sistema consisteix en la creació d'una instància de la classe arrel i en executar el procediment arrel. En general, això crea nous objectes, crida noves característiques, i així successivament. Eiffel té cinc instruccions bàsiques executables: assignació, creació d'objectes, crida de rutina, condició i iteració. Les estructures Eiffel de control són estrictes en el compliment de la programació estructurada: cada bloc té exactament una entrada i exactament una sortida. AbastA diferència de molts llenguatges orientats a l'objecte, però com Smalltalk, Eiffel no permet una assignació en els camps dels objectes, excepte dins de les característiques d'un objecte. Eiffel posa l'accent en amagar la informació i l'abstracció de dades, en requerir interfícies formals per a la mutació de dades. Per dir-ho en el llenguatge d'altres llenguatges de programació orientats a l'objecte, tots els camps Eiffel són "privats", i els mètodes "set" ("setters") són necessaris per modificar-ne els valors. Un resultat d'això és que un mètode "set" pot, i normalment ho fa, implementar els invariants per als quals Eiffel proporciona sintaxi. "Hola, món!"El primer contacte amb un llenguatge de programació es fa sovint amb l'ús d'un programa "Hola, món!". Aquest programa escrit en Eiffel podria ser: class
HOLA_MON
create
fes
feature
fes
do
print ("Hola, món!%N")
end --fes
end --HOLA_MON
Aquest programa conté la classe Disseny per ContracteEl concepte de disseny per contracte és fonamental per Eiffel. Els mecanismes estan estretament integrats amb el llenguatge. Els contractes guien la redefinició de les característiques a l'herència.
A més, el llenguatge suporta una "instrucció de verificació" ("check instruction" en anglès) (una espècie de "asserció") i els invariants de bucle. Característiques, ordres, i consultesLa propietat principal d'una classe és que conté un conjunt de característiques. Com una classe representa un conjunt d'objectes en temps d'execució, o "casos", una característica és un atribut o una operació en aquests objectes. Hi ha dos tipus de funcions: consultes i ordres. Una consulta proporciona informació sobre una instància. Una ordre modifica una instància. La distinció consulta-ordre és important per al mètode Eiffel. En particular:
SobrecàrregaEiffel no permet la sobrecàrrega d'arguments. Cada nom de característica dins d'una classe sempre s'assigna a una característica específica dins de la classe. Un nom, dins d'una classe, significa una cosa. Aquesta opció de disseny ajuda a la legibilitat de les classes, evitant una de les causes d'ambigüitat sobre quina la rutina serà invocada amb una crida. També simplifica el mecanisme de llenguatge. En particular, això és el que fa possible mecanisme d'herència múltiple d'Eiffel.[4] Els noms poden, per descomptat, ser reutilitzats en diferents classes. Per exemple, l'operador GenericitatLes classes poden ser genèriques, per expressar que estan parametritzades per tipus. Els paràmetres genèrics apareixen entre claudàtors: class LLISTA [G] ...
camp: G do ... end
posa (x: G) do ... end
La n := il.camp
wl.posa (w)
També és possible tenir "restriccions" dels paràmetres formals, de manera que el paràmetre real ha d'heretar d'una classe donada, la "restricció". Per exemple, en class TAULA_HASH [G, CLAU -> HASHABLE]
una derivació Fonaments de l'herènciaPer heretar d'una altra o altres, una classe inclourà una clàusula d'heretar al principi: class C inherit
A
B
-- ... Resta de la declaració de la classe ...
La classe pot redefinir (anul·lar) algunes o totes les característiques heretades. Això ha de ser declarat explícitament al començament de la classe a través de la clàusula class C inherit
A
redefine f, g, h end
B
redefine u, v end
Classes i característiques diferidesLes classes es poden definir amb Les classes diferides tenen un paper semblant al de les interfícies en llenguatges com Java, encara que molts teòrics de la programació orientada a l'objecte es creuen interfícies siguin en gran manera una resposta a la manca de Java de l'herència múltiple (que té Eiffel). Canvi de nomUna classe que hereta d'una altra o altres aconsegueix totes les seves característiques, per defecte amb els seus noms originals. Pot, però, canviar-ne el nom a través de la clàusula TuplesEls tipus tuples poden ser vistos com una forma simple de classe, proporcionant només els atributs i el corresponent mètode "set". Un tipus tupla típic TUPLE [nom: STRING; pes: REAL; data: DATE]
i podria ser utilitzat per descriure una simple d'acta de naixement si no fos necessària una classe. Un exemple d'aquesta tupla és simplement una seqüència de valors amb el tipus donat, entre parèntesis, com ["Maria", 3.5, anit]
Els components d'una tupla com a tal es poden accedir si les etiquetes de la tupla són atributs d'una classe, per exemple, si Gràcies a la noció d'assignador d'ordres (vegeu més endavant), la notació de punts també es pot utilitzar per assignar els components d'aquesta tupla, com en t.pes := t.pes + 0.5
Les etiquetes tupla són opcionals, de manera que també és possible escriure un tipus tupla com L'especificació precisa de, per exemple, AgentsEl mecanisme de l'"agent" d'Eiffel agrupa les operacions dins dels objectes. Aquest mecanisme pot ser utilitzat per a la iteració, la programació orientada a esdeveniments, i en altres contextos en què és útil per passar operacions al voltant de l'estructura del programa. Altres llenguatges de programació, especialment els que posen l'accent en la programació funcional, permeten un patró similar amb les continuacions, clausures, o generadors; els agents Eiffel emfatitzen el paradigma dels llenguatges orientats a l'objecte, i l'ús d'una sintaxi i semàntica similar als blocs de codi en Smalltalk i Ruby. Per exemple, per executar el bloc llista_propia.fer_tot (agent accio_propia)
Per executar llista_propia.fer_si (agent accio_propia, agent condicio_propia)
En aquests exemples, a.call ([x])
cridarà a la rutina original amb l'argument És possible mantenir alguns arguments per a un agent oberts (open en anglès) i fer els altres tancats (closed en anglès). Els arguments oberts es passen com a arguments per a la crida ( llista_propia.fer_tot (agent accio2 (?, y))
itera La distinció entre operands oberts i tancats (operands = arguments + objectiu) correspon a la distinció entre les variables lliures i lligades en el càlcul lambda. Un agent d'expressió, com ara El mecanisme d'agent ha estat recentment generalitzat per permetre la definició d'un agent sense fer referència a una rutina existent (com llista_propia.fer_tot (agent (s: STRING)
require
no_void: s /= Void
do
s.append_character (',')
ensure
appended: s.count = old s.count + 1
end)
L'agent en línia s'ha passat aquí pot tenir tota la faramalla d'una rutina normal, incloent precondició, postcondició, la clàusula de rescat (aquí no s'usa), i una signatura completa. Això evita la definició de rutines quan tot el que es necessita és un càlcul que s'agruparà en un agent. Això és útil en particular per als contractes, com a en una clàusula invariant que expressa que tots els elements d'una llista són positius: llista_propia.per_a_tots (agent (x: INTEGER): BOOLEAN do Result := (x > 0) end)
El mecanisme agent actual deixa una possibilitat d'error en temps d'execució (en cas d'una rutina amb n arguments es passi a un agent que està esperant m arguments amb m < n). Això pot evitar-se mitjançant un control en temps d'execució a través de la precondició Rutines d'execució únicaEl resultat d'una rutina pot ser emmagatzemat en memòria cau (caché en anglès) amb la paraula clau objecte_compartit: ALGUN_TIPUS
once
create Result.fer (args)
-- Això crea l'objecte i retorna una referència a la mateixa a través de 'Result'.
end --objecte_compartit
L'objecte retornat - Sovint, les "rutines d'execució única", realitzen una inicialització necessària: múltiples crides a una biblioteca (library en anglès) que poden incloure una crida al procediment d'inicialització, però només la primera crida es realitzen les accions requerides. Usant aquest patró la inicialització pot ser descentralitzada, evitant la necessitat d'un mòdul especial d'inicialització. Les "rutines d'execució única" són similars en propòsit i efecte al patró singleton de molts llenguatges de programació, i el patró utilitzat per Borg al Python. Per defecte, una "rutines d'execució única" s'anomena una vegada per fil d'execució (once per thread en anglès). La semàntica es pot ajustar a una vegada per procés o una vegada per objecte qualifica-te'l amb una paraula clau "once", per exemple, ConversionsEiffel proporciona un mecanisme per permetre les conversions entre diferents tipus. El mecanisme coexisteix amb el d'herència i el complementa. Per evitar qualsevol confusió entre els dos mecanismes, el disseny ha de complir el següent principi:
Per exemple El mecanisme de conversió simplement generalitza les normes ad hoc de conversió (tal com entre enters - string_meu := data_meva
com un accés directe per l'ús de la creació explícita d'un objecte amb un procediment de conversió: create string_meu.fer_de_data (data_meva)
Per fer la primera forma possible com a sinònim de la segona, n'hi ha prou amb incloure el procediment de creació (constructor) Com a un altre exemple, si existeix un procediment de conversió inclòs en Dia_de_la_Bastilla := [14, "Juliol", 1789]
Tractament d'excepcionsEl tractament d'excepcions en Eiffel es basa en els principis de disseny per contracte. Per exemple, es produeix una excepció quan qui crida a una rutina no satisfà la precondició, o quan a una rutina no es pot garantir el compliment de la postcondició. En Eiffel, el tractament d'excepcions no s'utilitza per a les estructures de control o per corregir errors de les dades d'entrada. Un controlador d'excepcions Eiffel es defineix utilitzant la paraula clau connecta_al_servidor (servidor: SOCKET)
-- Es connecta a un servidor o renuncia després de 10 intents.
require
servidor /= Void and then servidor.addressa /= Void
local
intents: INTEGER
do
servidor.connecta
ensure
connectat: servidor.es_connectat
rescue
if intents < 10 then
intents := intents + 1
retry
end --if
end --connecta_al_servidor
Aquest exemple és, sens dubte, imperfecte, però en els programes més simples hauria d'estar previst que pugui fallar la connexió. Per a la majoria dels programes seria millor un nom de rutina com ConcurrènciaHi ha disponibles diverses biblioteques (libraries en anglès) de xarxes i de fils d'execució (threads en anglès), com ara EiffelNet i EiffelThreads. Un model de concurrència d'Eiffel, basat en els conceptes de disseny per contracte, és el SCOOP (programari), o Programació Concurrent Simple Orientada a l'Objecte (Simple Concurrent Object Oriented Programming en anglès), encara no forma part de la definició oficial del llenguatge, però disponible com un "add-on" de ETH Zurich. CAMEO[6] és una variació (no implementada) de SCOOP d'Eiffel. La concurrència també interacciona amb les excepcions. Les excepcions asíncrones poden ser un problema (una rutina activa una excepció després que la seva crida s'ha acabat).[7] Sintaxi d'operadors i claudàtors, les ordres d'assignacióLa visió del càlcul a Eiffel és completament orientada a l'objecte en el sentit que cada operació és relativa a un objecte, l'"objectiu". Així, per exemple, una suma [1] a + b
és conceptualment entesa com si es tractés d'una crida a la funció [2] a.mes (b)
amb l'objectiu Per descomptat, [1] és la sintaxi convencional i la preferida normalment. La sintaxi de l'operador fa possible l'ús d'una o de l'altra manera, en declarar la funció (per exemple, a mes alias "+" (un_altre: INTEGER): INTEGER
-- ... Declaració normal de la funció...
end
La gamma d'operadors que poden utilitzar-se com a "àlies" (alias en anglès) és bastant ampli, i inclouen operadors predefinits com "+" però també "els operadors lliures" fets de símbols no alfanumèrics. Això fa possible dissenyar notacions especials d'infixos i prefixos, per exemple, en aplicacions de matemàtiques de física. Cada classe podrà, a més, tenir una funció àlies de "[]", l'operador "claudàtor", permetent que la notació numero := Llibreta_de_telefons ["JULI FERRER"]
Les "ordres d'assignació" són un mecanisme d'acompanyament dissenyat amb el mateix esperit de permetre la solidesa, la convenient notació reinterpretada en el marc de la programació orientada a l'objecte. Les ordres d'assignació permeten sintaxi d'assignació com a crides a procediments "setter". Una assignació adequada no pot ser de la forma camp alias "[]" (clau: STRING): ELEMENT [3]
-- L'element de la clau 'clau'.
-- (interrogació del "Getter")
do
...
end --camp
posa (e: ELEMENT; clau: STRING)
-- Insertar l'element 'e', associant-lo amb la clau 'clau'.
-- (ordre "Setter")
do
...
end --posa
Després, per inserir un element que ha d'utilitzar una crida explícita a l'ordre setter: [4] Llibreta_de_telefons.posa (Nova_persona, "JULI FERRER")
És possible escriure aquest equivalent com [5] Llibreta_de_telefons ["JULI FERRER"] := Nova_persona
(De la mateixa manera que camp alias "[]" (key: STRING): ELEMENT assign posa
Això declara Nota: La llista d'arguments de l'assignació d' Propietats lèxiques i sintàctiquesEiffel no distingeix entre majúscules i minúscules. Això vol dir que Els comentaris són introduïts per -- (dos guions consecutius) i s'estenen fins al final de línia. El punt i coma (;), com a separador d'instruccions, és opcional. La majoria de les vegades el punt i coma és omès, excepte per separar múltiples instruccions en una línia. Això es tradueix en menys desordre a la pàgina del programa. No hi ha niament de les declaracions de les característiques i de la classe. Com a resultat l'estructura d'una classe Eiffel és simple: algunes clàusules a nivell de classe (herència, invariant) i una successió de declaracions de característiques, estan totes al mateix nivell. S'acostuma a agrupar les característiques en diferents "clàusules de característiques" per facilitar-ne més lectura, amb un conjunt estàndard d'etiquetes de característica bàsica que figuren en un ordre estàndard, per exemple: class TAULA_HASH [ELEMENT, KEY -> HASHABLE] inherit TABLE [ELEMENT]
feature -- Inicialització
-- ... Declaracions de les ordres d'inicialització (procediments de creació/constructors) ...
feature -- Accés
-- ... Declaracions de les consultes no booleanes sobre l'estat de l'objecte, per exemple, camp ...
feature -- Informe de situació
-- ... Declaracions de consultes booleanes sobre l'estat de l'objecte, per exemple, es-buida ...
feature -- el canvi de l'element
-- ... Declaracions de ordres que canvien l'estructura, per exemple, posa ...
-- etc.
end -- TAULA_HASH
En contrast amb els llenguatges de programació funcionals més enrevessats, Eiffel fa una clara distinció entre les expressions i les instruccions. Això està en consonància amb el principi de la distinció consulta-ordre del mètode Eiffel. Convencions d'estilGran part de la documentació d'Eiffel utilitza les convencions d'estil distintives, dissenyades per vetllar per un aspecte consistent. Algunes d'aquestes convencions s'apliquen al format de codi en si, i altres per a la representació tipogràfica estàndard del codi Eiffel en formats i publicacions en les que aquestes convencions són possibles. Mentre que el llenguatge no distingeix entre majúscules i minúscules, les normes d'estil de prescriuen que els noms de classe estiguin totalment en majúscules ( L'especificació d'Eiffel inclou directrius per als textos de programari que mostra en format composició tipogràfica: paraules clau en class
HOLA_MON create fes feature fes do print ("Hola, món!") end --fesend --HOLA_MON Interfícies amb altres eines i llenguatgesEiffel és un llenguatge purament orientat a l'objecte, però proporciona una arquitectura oberta per a la interconnexió amb programari "extern" en qualsevol altre llenguatge de programació. És possible, per exemple, programar a nivell màquina i sistema operatiu en C. Eiffel proporciona una interfície senzilla per a les rutines en C, inclòs el suport a "C en línia" (escriure el cos d'una rutina d'Eiffel en C, en general per a petites operacions a nivell màquina). Encara que no existeix una connexió directa entre Eiffel i C, molts compiladors Eiffel (Visual Eiffel n'és una excepció) el codi font sortit de C com un llenguatge intermedi, a sotmetre's a un compilador de C, per a l'optimització i la portabilitat. El compilador Eiffel de tecomp pot executar codi Eiffel directament (com un intèrpret) sense haver de passar a través d'un codi C intermedi ni emetre codi C que es passarà a un compilador de C per obtenir el codi natiu optimitzat. En .NET, el compilador EiffelStudio genera directament codi en CIL (Common Intermediate Language). El compilador SmartEiffel pot també generar la sortida en bytecode de Java. Referències
Enllaços externs
|