stringtranslate.com

Oxygene (lenguaje de programación)

Oxygene (antes conocido como Chrome ) es un lenguaje de programación desarrollado por RemObjects Software para Common Language Infrastructure de Microsoft , la plataforma Java y Cocoa . Oxygene se basa en Object Pascal de Delphi , pero también tiene influencias de C# , Eiffel , Java , F# y otros lenguajes.

En comparación con el ahora obsoleto Delphi.NET , Oxygene no enfatiza la compatibilidad total con versiones anteriores, sino que está diseñado para ser una "reinvención" del lenguaje, ser un buen ciudadano en las plataformas de desarrollo administradas y aprovechar todas las características y tecnologías proporcionadas por los entornos de ejecución .NET y Java.

Oxygene es un producto comercial y ofrece una integración completa con el IDE Visual Studio de Microsoft en Windows y su propio IDE llamado Fire para su uso en macOS . Oxygene es uno de los seis lenguajes compatibles con la cadena de herramientas subyacente Elements Compiler, junto con C# , Swift , Java , Go y Mercury (basado en Visual Basic (.NET) ).

De 2008 a 2012, RemObjects Software licenció su compilador y tecnología IDE a Embarcadero para que se usara como compilador de backend en su producto Embarcadero Prism. [2] A partir del otoño de 2011, Oxygene estuvo disponible en dos ediciones independientes, y la segunda edición agregó soporte para los entornos de ejecución de Java y Android. A partir del lanzamiento de XE4, Embarcadero Prism ya no forma parte del SKU de RAD Studio. Existen numerosas rutas de soporte y actualización para que los clientes de Prism migren a Oxygene. [3] A partir de 2016, solo hay una edición de Oxygene, que permite el desarrollo en Windows o macOS, y que puede crear ejecutables para Windows, Linux, WebAssembly .NET, iOS, Android, Java y macOS.

El idioma

El lenguaje Oxygene tiene su origen en Object Pascal en general y Delphi en particular, pero fue diseñado para reflejar las pautas de programación .NET y para crear conjuntos totalmente compatibles con CLR. Por lo tanto, se han eliminado o revisado algunas características menores del lenguaje conocidas de Object Pascal – Delphi, mientras que se han agregado al lenguaje muchas características nuevas y más modernas, como genéricos o secuencias y consultas.

Oxygene es un lenguaje de programación orientado a objetos . Por lo tanto, utiliza clases, que pueden contener datos y ejecutar código, para diseñar programas. [ Aclaración necesaria ] Las clases son "prototipos" de objetos, como la idea de una manzana es el prototipo de la manzana que uno puede comprar en una tienda. Se sabe que una manzana tiene un color y que se puede pelar: esos son los datos y el "código" ejecutable para la clase manzana.

Oxygene proporciona soporte a nivel de lenguaje para algunas características de la programación paralela. El objetivo es utilizar todos los núcleos o procesadores de una computadora para mejorar el rendimiento. Para alcanzar este objetivo, las tareas deben distribuirse entre varios subprocesos. La clase de .NET FrameworkThreadPool ofrecía una forma de trabajar de manera eficiente con varios subprocesos. La biblioteca de tareas paralelas (TPL) se introdujo en .NET 4.0 para proporcionar más funciones para la programación paralela.

Los operadores se pueden sobrecargar en Oxygene utilizando la class operatorsintaxis:

operador de clase implícito ( i : Entero ) : MiClase ;      

Tenga en cuenta que, para la sobrecarga del operador, cada operador tiene un nombre que debe usarse en la sintaxis de sobrecarga del operador, porque, por ejemplo, "+" no sería un nombre de método válido en Oxygene. [4]

Estructura del programa

Oxygene no utiliza "Unidades" como Delphi, sino que utiliza espacios de nombres .NET para organizar y agrupar tipos. Un espacio de nombres puede abarcar varios archivos (y ensambles), pero un archivo solo puede contener tipos de un espacio de nombres. Este espacio de nombres se define en la parte superior del archivo:

espacio de nombres ConsoleApplication1;

Los archivos Oxygene se dividen en una interfaz y una sección de implementación, que es la estructura conocida de Delphi. La sección de interfaz sigue a la declaración del espacio de nombres. Contiene la usescláusula que en Oxygene importa tipos de otros espacios de nombres:

utiliza Sistema . Linq ; 

Los espacios de nombres importados deben estar en el propio proyecto o en los ensambles a los que se hace referencia. A diferencia de C#, en Oxygene no se pueden definir nombres de alias para espacios de nombres, solo para nombres de un solo tipo (consulte a continuación).

A continuación de la usescláusula, un archivo contiene declaraciones de tipo, tal como se conocen en Delphi:

interfaztipo ConsoleApp = clase clase pública método Main ; fin ;        

Al igual que en C#, el método Main es el punto de entrada de cada programa. Puede tener un parámetro args : Array of Stringpara pasar argumentos de línea de comandos al programa.

Se pueden declarar más tipos sin repetir la typepalabra clave.

La implementación de los métodos declarados se coloca en la sección de implementación:

implementaciónmétodo de clase ConsoleApp . Main ; begin // agrega tu propio código aquí Console . WriteLine ( 'Hola mundo.' ) ; end ;    fin .

Los archivos siempre terminan conend.

Tipos

Como lenguaje .NET, Oxygene utiliza el sistema de tipos .NET: hay tipos de valor (como estructuras) y tipos de referencia (como matrices o clases).

Aunque no introduce tipos "predefinidos" propios, Oxygene ofrece nombres genéricos más "pascalianos" para algunos de ellos, [5] de modo que, por ejemplo, se System.Int32pueden utilizar como Integery Boolean( System.Boolean), Char( System.Char), Real( System.Double) y también se unen a la familia de nombres de tipos pascal. El carácter de estructura de estos tipos, que es parte de .NET, se conserva por completo.

Como en todos los lenguajes .NET, los tipos en Oxygene tienen una visibilidad. En Oxygene, la visibilidad predeterminada es assembly, que es equivalente a la internalvisibilidad en C#. La otra visibilidad de tipo posible es public.

tipo MiClase = clase pública fin ;    

La visibilidad se puede configurar para cada tipo definido (clases, interfaces, registros, ...).

Se puede definir un nombre de alias para los tipos, que se pueden usar localmente o en otros ensamblajes de Oxygene.

tipo IntList = public List < Integer >; //visible en otros ensamblados Oxygene SecretEnumerable = IEnumerable < String >; //no visible en otros ensamblados         

Los alias de tipo públicos no serán visibles para otros idiomas.

Archivos

Los registros son el nombre que reciben las estructuras .NET en Oxygene. Se declaran igual que las clases, pero con la recordpalabra clave:

tipo MyRecord = método de registro Foo ; fin ;      

Como son solo estructuras .NET, los registros pueden tener campos, métodos y propiedades, pero no tienen herencia y no pueden implementar interfaces .

Interfaces

Las interfaces son un concepto muy importante en el mundo .NET, el propio framework hace un uso intensivo de ellas. Las interfaces son la especificación de un pequeño conjunto de métodos, propiedades y eventos que una clase debe implementar al implementar la interfaz. Por ejemplo, la interfaz IEnumerable<T>especifica el GetEnumeratormétodo que se utiliza para iterar sobre secuencias.

Las interfaces se declaran igual que las clases:

tipo MyInterface = interfaz pública método MakeItSo : IEnumerable ; propiedad Bar : String lectura escritura ; fin ;               

Tenga en cuenta que, para las propiedades, el captador y el definidor no se especifican explícitamente.

Delegados

Los delegados definen firmas para los métodos, de modo que estos métodos se puedan pasar en parámetros (por ejemplo, devoluciones de llamadas) o almacenar en variables, etc. Son el equivalente de NET con seguridad de tipos a los punteros de función. También se utilizan en eventos. Al asignar un método a un delegado, uno tiene que usar el @operador, de modo que el compilador sepa que uno no quiere llamar al método, sino simplemente asignarlo.

Oxygene puede crear delegados anónimos; por ejemplo, se pueden pasar métodos al Invokemétodo de un control sin declarar el delegado:

método MainForm . MainForm_Load ( remitente : System . Object ; e : System . EventArgs ) ;     inicio Invoke ( @ DoSomething ) ; fin ; 

DoSomethingEl compilador creará un delegado anónimo con la firma del método .

Oxygene admite delegados polimórficos, lo que significa que los delegados que tienen parámetros de tipos descendentes son compatibles con la asignación. Supongamos que hay dos clases MyClassy MyClassEx = class(MyClass), entonces en el siguiente código BlubbExes compatible con la asignación Blubb.

tipo delegado Blubb ( remitente : Objeto ; m : MiClase ) ; delegado BlubbEx ( remitente : Objeto ; mx : MiClaseEx ) ;              

Los campos se pueden usar para delegar la implementación de una interfaz, si el tipo del que son implementa esta interfaz:

Implementador = clase pública ( IMyInterface ) // ... implementar interfaz ... fin ;    MyClass = public class ( IMyInterface ) fSomeImplementor : Implementor ; public implements IMyInterface ; //se encarga de implementar la interfaz end ;          

En este ejemplo, el compilador creará métodos y propiedades públicos en MyClass, que invocarán los métodos/propiedades de fSomeImplementor, para implementar los miembros de IMyInterface. Esto se puede utilizar para proporcionar una funcionalidad similar a la de un mixin. [6]

Métodos anónimos

Los métodos anónimos se implementan dentro de otros métodos. No se puede acceder a ellos fuera del método a menos que se almacenen dentro de un campo delegado. Los métodos anónimos pueden usar las variables locales del método en el que se implementan y los campos de la clase a la que pertenecen.

Los métodos anónimos son especialmente útiles cuando se trabaja con código que se supone que debe ejecutarse en un hilo de GUI, lo que se hace en .NET pasando un método al Invokemétodo ( Control.Invokeen WinForms, Dispatcher.Invokeen WPF):

método Window1 . PredictNearFuture ; //declarado como asíncrono en la interfaz   begin // ... Calcular el resultado aquí, almacenar en la variable "theFuture" Dispatcher . Invoke ( DispatcherPriority . ApplicationIdle , método ; begin theFutureTextBox . Text := theFuture ; end ) ; end ;        

Los métodos anónimos también pueden tener parámetros:

método Window1 . PredictNearFuture ; //declarado como async en la interfaz   begin // ... Calcular el resultado aquí, almacenar en la variable "theFuture" Dispatcher . Invoke ( DispatcherPriority . ApplicationIdle , método ( aFuture : String ) ; begin theFutureTextBox . Text := aFuture ; end , theFuture ) ; end ;            

Ambos códigos fuente utilizan delegados anónimos.

Notificación de propiedad

La notificación de propiedades se utiliza principalmente para la vinculación de datos, cuando la GUI debe saber cuándo cambia el valor de una propiedad. El marco .NET proporciona las interfaces INotifyPropertyChangedy INotifyPropertyChanging(en .NET 3.5) para este propósito. Estas interfaces definen eventos que deben activarse cuando se cambia o se modificó una propiedad.

Oxygene proporciona el notifymodificador que se puede utilizar en las propiedades. Si se utiliza este modificador, el compilador agregará las interfaces a la clase, las implementará y creará código para generar los eventos cuando la propiedad cambie o haya cambiado.

propiedad Foo : String leer fFoo escribir SetFoo ; notificar ; propiedad Bar : String ; notificar 'Blubb' ; //notificará que se cambió la propiedad "Blubb" en lugar de "Bar"              

El modificador se puede utilizar en propiedades que tienen un método de establecimiento. El código para generar los eventos se agregará a este método durante el tiempo de compilación.

Ejemplos de código

Hola Mundo

espacio de nombres HelloWorld ;  interfaztipo HelloClass = clase clase pública método Main ; fin ;        implementaciónmétodo de clase HelloClass . Main ; begin writeLn ( '¡Hola mundo!' ) ; end ;   fin .

Contenedor genérico

espacio de nombres GenericContainer ;  interfaztipo TestApp = clase clase pública método Main ; fin ;         Persona = clase propiedad pública Nombre : String ; propiedad Apellido : String ; fin ;           implementaciónutiliza Sistema . Colecciones . Genérico ; clase método TestApp . Main ; begin var myList := new List < Person >; //inferencia de tipo myList . Add ( new Person ( FirstName := 'John' , LastName := 'Doe' ) ) ; myList . Add ( new Person ( FirstName := 'Jane' , LastName := 'Doe' )) ; myList . Add ( new Person ( FirstName := 'James' , LastName := 'Doe' )) ; Console . WriteLine ( myList [ 1 ] . FirstName ) ; //No se necesita conversión Console . ReadLine ; end ;                                   fin .

Método genérico

espacio de nombres GenericMethodTest ;  interfaztipo GenericMethodTest = clase estática clase pública método Main ; clase privada método Swap < T > ( var left , right : T ) ; clase método DoSwap < T > ( left , right : T ) ; fin ;                   implementaciónclase método GenericMethodTest . DoSwap < T > ( izquierda , derecha : T ) ; comienzo var a := izquierda ; var b := derecha ; Console . WriteLine ( 'Tipo: {0}' , typeof ( T )) ; Console . WriteLine ( '-> a = {0}, b = {1}' , a , b ) ; Swap < T > ( var a , var b ) ; Console . WriteLine ( '-> a = {0}, b = {1}' , a , b ) ; fin ;                           método de clase GenericMethodTest . Main ; begin var a := 23 ; // inferencia de tipo var b := 15 ; DoSwap < Integer > ( a , b ) ; // no hay conversión descendente a Object en este método.              var aa := 'abc' ; // inferencia de tipo var bb := 'def' ; DoSwap < String > ( aa , bb ) ; // no hay conversión descendente a Object en este método.           DoSwap ( 1.1 , 1.2 ) ; // inferencia de tipos para parámetros genéricos Console.ReadLine () ; fin ;   método de clase GenericMethodTest . Swap < T > ( var izquierda , derecha : T ) ; comienzo var temp := izquierda ; izquierda := derecha ; derecha := temp ; fin ;               fin .

Salida del programa:

Tipo: Sistema.Int32-> a = 23, b = 15-> a = 15, b = 23Tipo: System.String-> a = abc, b = definición-> a = definición, b = abcTipo: Sistema.Doble-> a = 1,1, b = 1,2-> a = 1,2, b = 1,1

Diferencias entre Delphi y Oxygene

Crítica

A algunas personas [¿ quiénes? ] les gustaría portar su código Win32 de Delphi a Oxygene sin realizar cambios importantes. Esto no es posible porque, si bien Oxygene se parece a Delphi, hay suficientes cambios como para que sea incompatible con una simple recompilación. Si bien el nombre le da la apariencia de otra versión de Delphi, eso no es completamente cierto. [7]

Además de la diferencia de lenguaje, el marco de la Biblioteca de componentes visuales no está disponible en Oxygene. [8] Esto hace que la portabilidad sea aún más difícil porque el código clásico de Delphi depende en gran medida de VCL.

Véase también

Referencias

  1. ^ "Evolución del lenguaje Oxygene | Oxygene | Elements". Archivado desde el original el 5 de enero de 2018. Consultado el 4 de enero de 2018 .
  2. ^ "Página de Embarcadero Prism, en la parte inferior de la página una imagen que indica que funciona con RemObjects Oxygene". Archivado desde el original el 27 de diciembre de 2011. Consultado el 14 de diciembre de 2011 .
  3. ^ "Prism XE4, ¿dónde estás? | RemObjects Blogs". Archivado desde el original el 20 de junio de 2013. Consultado el 6 de junio de 2013 .
  4. ^ "Sobrecarga del operador - Delphi Prism". Archivado desde el original el 8 de julio de 2011. Consultado el 9 de enero de 2010 .
  5. ^ "Tipos incorporados - Prisma de Delphi". Archivado desde el original el 8 de julio de 2011. Consultado el 10 de enero de 2010 .
  6. ^ "Proporcionar funcionalidad similar a Mixin - Delphi Prism". Archivado desde el original el 8 de julio de 2011. Consultado el 17 de enero de 2010 .
  7. ^ "Una discusión en Stack Overflow donde la gente comenta que Oxygene no es Delphi Win32". Archivado desde el original el 25 de octubre de 2012. Consultado el 25 de julio de 2016 .
  8. ^ "Revisión de Delphi Prism 2010 donde se indica en el tercer párrafo que VCL.net no está disponible". Archivado desde el original el 4 de septiembre de 2009. Consultado el 14 de diciembre de 2009 .

Enlaces externos