Oxygene (programovací jazyk)

Z Wikipedie, otevřené encyklopedie
Skočit na navigaci Skočit na vyhledávání
Oxygene
Vývojář RemObjects Software
Poslední verze 7.1.73 (23. 4. 2014)
Ovlivněn jazyky Object Pascal, C#
OS Common Language Infrastructure, Java
Licence Komerční
Web www.remobjects.com/oxygene

Oxygene (dříve známý jako Chrome) je programovací jazyk vyvinutý společností RemObjects Software pro Microsoft Common Language Infrastructure a Java platformu. Oxygene je založen na Object Pascalu, ale byl také ovlivněn jazyky C#, Eiffel, Java, F# a dalšími.

V porovnání s nyní zastaralým Delphi.NET, Oxygene neklade takový důraz na zpětnou kompatibilitu, ale je vyvíjen, aby byl "znovuobjevením" jazyka, aby vyhovoval na řízené vývojové platformy, pod vlivem všech technologií poskytovaných .NET a Java runtime.

Oxygene nabízí plnou integraci do Visual Studia 2010 and 2012 jako komerční produkt a zdarma dostupný kompilátor pro příkazovou řádku.

Od roku 2008, RemObjects Software licencoval svůj kompilátor a IDE technologii Embarcadero Technologies k využití v jejich produktu Embarcadero Prism. Od podzimu 2011 je Oxygene dostupný ve dvou edicích, kde druhá edice přidává podporu pro Javu a Android runtime. Od verze XE4, Embarcadero Prism již není součástí RAD Studia. Několik záplat pro Prism umožňuje uživatelům přechod na Oxygene.[1]

Jazyk[editovat | editovat zdroj]

Jazyk Oxygene má obecně svůj původ v Object Pascalu, přesněji v Delphi, ale byl navržen tak, aby odrážel vzor .NET programování a vytvořil plně CLR vyhovující sestavení. Proto některé méně významné vlastnosti známé z Object Pascalu / Delphi byly odstraněny nebo upraveny, zatímco mnoho nových a moderních vlastností, jako genericita, sekvence a fronty, byly do jazyka přidány.

Oxygene je objektově orientovaný jazyk, takže používá třídy.

Oxygene poskytuje na úrovni jazyka podporu pro některé vlastnosti paralelního programování. Cílem je využít všech jader procesoru počítače pro zlepšení výkonu. K dosažení tohoto cíle musí být procesy rozděleny mezi několik vláken. Třída ThreadPool z .NET frameworku nabízí cestu jak efektivně pracovat s několika vlákny. Ve verzi .NET 4.0 byla představena knihovna TPL za účelem poskytnutí více možností pro podporu paralelního programování.

Operátory mohou být v Oxygenu přetíženy pomocí syntaxe class operator:

class operator implicit(i : Integer) : MyClass;

Počítejte s tím, že při přetížení operátoru má každý operátor jméno, které musí být použito v syntaxi přetížení operátoru, protože například "+" by nebylo validním názvem pro metodu v Oxygenu.[2]

Struktura programu[editovat | editovat zdroj]

Oxygene nepoužívá "jednotky" (units) jako Delphi, ale používá jmenné prostory .NET pro organizaci seskupování typů. Jmenný prostor může pokrývat více souborů (a sestavení), ale jeden soubor může obsahovat typy pouze jednoho jmenného prostoru. Tento jmenný prostor je definován na úplném začátku souboru:

namespace ConsoleApplication1;

Soubory Oxygenu jsou rozděleny na sekci interface pro rozhraní a sekci implementation pro implementaci, což je struktura známá z Delphi. Sekce rozhraní následuje za deklarací jmenného prostoru. Obsahuje klauzuli uses, která v Oxygenenu importuje typy dalších jmenných prostorů:

uses 
  System.Linq;

Importovaný jmenný prostor se musí nacházet ve stejném projektu nebo v odkazovaných sestaveních. Na rozdíl od C#, v Oxygenenu nemohou být definovány přezdívky jmenných prostorů. Mohou být definovány pouze pro názvy jednotkového typu (viz níže).

Za klauzulí uses v souboru následuje deklarace typů, stejně jak je to známé z Delphi:

interface

type
  ConsoleApp = class
  public
    class method Main;
  end;

Stejně jako v C#, metoda Main je vstupním bodem každého programu. Může mít parametr args : Array of String pro zasílání argumentů z příkazové řádky do programu.

Další typy mohou být deklarovány bez opakování klíčového slova type.

Implementace deklarovaných metod je umístěna v sekci implementation:

implementation

class method ConsoleApp.Main;
begin
  // zde přidejte svůj vlastní kód
  Console.WriteLine('Hello World.');
end;

end.

Soubory jsou vždy zakončeny end.

Typy[editovat | editovat zdroj]

Jako jazyk .NET, Oxygene používá systém typů .NET: Jsou zde hodnotové typy (jako struktury) a referenční typy (jako pole nebo třídy).

Ačkoli neposkytuje vlastní "předdefinované" typy, Oxygene nabízí po vzoru Pascalu pro některé z nich generické názvy,[3] takže například System.Int32 může být použit jako Integer a Boolean (System.Boolean), Char (System.Char), Real (System.Double) jsou také součástí typových jmen Pascalu. Strukturní znak těchto typů, který je součástí .NET, je zcela zachován.

Stejně jako všechny jazyky .NET i Oxygene má nastavení viditelnosti. V Oxygenenu je výchozí viditelnost assembly, což je ekvivalent viditelnosti internal z C#. Další možný typ viditelnosti je public.

type
  MyClass = public class
end;

Viditelnost může být nastavena pro každý definovaný typ (třídy, interfejsy, záznamy, ...).

Pro typy mohou být definovány přezdívky, což je možné použít lokálně nebo v jiných Oxygene sestaveních.

type
  IntList = public List<Integer>; //viditelný v jiných Oxygene sestaveních
  SecretEnumerable = IEnumerable<String>; //neviditelný v jiných sestaveních

Přezdívky typu public nejsou viditelné pro jiné jazyky.

Záznamy[editovat | editovat zdroj]

.NET struktury jsou v Oxygenu nazývány záznamy. Jsou deklarovány obdobně jako třídy, ale s klíčovým slovem record:

type
  MyRecord = record
    method Foo;
end;

Protože jsou to pouze .NET struktury, záznamy mohou mít pole, metody a vlastnosti, ale nemohou dědit a nemohou implementovat interfejs.

Interfejsy[editovat | editovat zdroj]

Interfejsy jsou velmi důležitým konceptem ve světě .NET, samotný framework je hojně využívá. Interfejsy jsou specifikací malých sad metod, vlastností a událostí, které musí třída implementovat, pokud implementuje interfejs. Na příklad interfejs IEnumerable<T> specifikuje metodu GetEnumerator, která se používá k procházení sekvencí.

Interfejsy se deklarují obdobně, jako třídy:

type
  MyInterface = public interface
    method MakeItSo : IEnumerable;
    property Bar : String read write;
end;

Vezměte prosím na vědomí, že gettery a settery nejsou pro vlastnosti explicitně specifikovány.

Delegáty[editovat | editovat zdroj]

Delegáty definují podpisy pro metody, takže tyto metody mohou být přeposílány v parametrech (např. callback) nebo uloženy v proměnných, atd. Jsou to typově bezpečné .NET ekvivalenty k ukazatelům funkcí. Jsou také využívány v událostech. Když se metoda přiřazuje k delegátu je potřeba použít operátor @, aby kompilátor věděl, že nemá metodu zavolat, ale pouze ji přiřadit.

Oxygene dokáže vytvářet anonymní delegáty, například metoda může být přeposlána k řídící metodě Invoke bez deklarace delegátu:

method MainForm.MainForm_Load(sender: System.Object; e: System.EventArgs);
begin
  Invoke(@DoSomething);
end;

Anonymní delegát s podpisem metody DoSomething bude vytvořen kompilátorem.

Oxygene podporuje polymorfní delegáty, to znamená, že delegáty, které mají parametry klesajících typů jsou přidělování-kompatibilní. Předpokládejte dvě třídy MyClass a MyClassEx = class(MyClass), v následujícím kódu je BlubbEx přidělování-kompatibilní k Blubb.

type
  delegate Blubb(sender : Object; m : MyClass);
  delegate BlubbEx(sender : Object; mx : MyClassEx);

Pole mohou být použity k delegování implementace interfejsu, když jejich typ implementuje tento interfejs:

Implementor = public class(IMyInterface)
  // ... implementace interfejsu ...
end;

MyClass = public class(IMyInterface)
  fSomeImplementor : Implementor; public implements IMyInterface; //postará se o implementaci interfejsu
end;

V tomto příkladu kompilátor vytvoří public metody a vlastnosti v MyClass, která volá metody / vlastnosti fSomeImplementor, k implementaci členů IMyInterface. Toho lze využít pro poskytnutí funkcionality podobné "Mixin".[4]

Anonymní metody[editovat | editovat zdroj]

Anonymní metody jsou implementovány uvnitř dalších metod. Nejsou přístupné z vnějšku metody, pokud nejsou uloženy uvnitř pole delegátů. Anonymní metody mohou používat lokální proměnné metody, ve které jsou implementovány a pole třídy, do které patří.

Anonymní třídy jsou obzvlášť užitečné při práci s kódem, který má být spuštěn ve vlákně GUI, čehož je dosaženo v .NET přeposláním metody do metody Invoke (Control.Invoke ve WinForms, Dispatcher.Invoke ve WPF):

method Window1.PredictNearFuture;  //deklarováno jako asynchronní v interfejsu
begin
  // ... Vypočti výsledek zde, ulož v proměnné "theFuture"
    Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, method; begin
      theFutureTextBox.Text := theFuture;
    end);
end;

Anonymní metody také mohou mít parametry:

method Window1.PredictNearFuture;  //deklarováno jako asynchronní v interfejsu
begin
  // ... Vypočti výsledek zde, ulož v proměnné "theFuture"
    Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, method(aFuture : String); begin
      theFutureTextBox.Text := aFuture ;
    end, theFuture);
end;

Oba zdrojové kódy používají anonymní delegáty.

Oznámení vlastnosti[editovat | editovat zdroj]

Oznámení vlastnosti se používá především pro přiřazování dat, když GUI potřebuje vědět, kdy se hodnota vlastnosti změnila. .NET framework poskytuje pro tyto účely interfejs INotifyPropertyChanged a INotifyPropertyChanging (ve verzi .NET 3.5). Tyto interfejsy definují události, které je potřeba spustit když se vlastnost změní / byla změněna.

Oxygene poskytuje modifikátor notify, který lze použít na vlastnosti. Pokud je tento modifikátor použit, kompilátor přidá interfejsy ke třídě, implementuje je a vytvoří kód, který vyvolá události, když se vlastnost změní / byla změněna.

property Foo : String read fFoo write SetFoo; notify;
property Bar : String; notify 'Blubb'; //oznámí, že vlastnost "Blubb" byla změněna namísto "Bar"

Modifikátor může být použit na vlastnosti, které mají setter metody. Kód pro vyvolání událostí bude poté přidán do této metody během kompilování.

Příklady[editovat | editovat zdroj]

Hello World[editovat | editovat zdroj]

namespace HelloWorld;
  
interface
 
type
  HelloClass = class
  public
    class method Main; 
  end;

implementation

class method HelloClass.Main;
begin
  System.Console.WriteLine('Hello World!');
end;

end.

Generický kontejner[editovat | editovat zdroj]

namespace GenericContainer;
 
interface

type
  TestApp = class
  public
    class method Main;
  end;

  Person = class
  public
    property FirstName: String;
    property LastName: String;      
  end;

implementation

uses 
  System.Collections.Generic;

class method TestApp.Main;
begin
  var myList := new List<Person>; //odvození typu
  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);  //Přetypování není nutné
  Console.ReadLine;        
end;

end.

Generická metoda[editovat | editovat zdroj]

namespace GenericMethodTest;

interface

type
GenericMethodTest = static class
public
  class method Main;
private
  class method Swap<T>(var left, right : T);
  class method DoSwap<T>(left, right : T);
end;

implementation

class method GenericMethodTest.DoSwap<T>(left, right : T);
begin
  var a := left;
  var b := right;
  Console.WriteLine('Type: {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);
end;

class method GenericMethodTest.Main;
begin
  var a := 23;// odvození typu
  var b := 15;
  DoSwap<Integer>(a, b); // žádné přetypování dolů k Object v této metodě.

  var aa := 'abc';// odvození typu
  var bb := 'def';
  DoSwap<String>(aa, bb); // žádné přetypování dolů k Object v této metodě.

  DoSwap(1.1, 1.2); // odvození typu pro generický parametr
  Console.ReadLine();
end;

class method GenericMethodTest.Swap<T>(var left, right : T);
begin
  var temp := left;
  left:= right;
  right := temp;
end;

end.

Výstup programu:

Type: System.Int32
-> a = 23, b = 15
-> a = 15, b = 23
Type: System.String
-> a = abc, b = def
-> a = def, b = abc
Type: System.Double
-> a = 1,1, b = 1,2
-> a = 1,2, b = 1,1

Rozdíly mezi nativním Delphi a Oxygenem[editovat | editovat zdroj]

  • unit: Nahrazeno klíčovým slovem namespace. Jelikož Oxygene nekompiluje po souborech, ale po projektech, nezávisí na názvu souboru. Místo toho je klíčové slovo unit nebo namespace použito k označení výchozího jmenného prostoru pro který jsou definovány všechny typy v daném souboru.
  • procedure a function: method je preferované klíčové slovo, přestože procedure a function stále fungují.
  • overload: V Oxygenu jsou všechny metody defaultně přetíženy, takže žádné speciální klíčové slovo není potřeba.
  • .Create(): Tento způsob volání konstruktoru byl nahrazen klíčovým slovem new. Stále může být ale nastaven v project options z důvodů zpětné kompatibility.
  • string: Znaky v řetězcích jsou zero-based a read-only. Řetězce mohou mít nulovou hodnotu, takže testování proti prázdným řetězcům není vždy vhodné.

Kritika[editovat | editovat zdroj]

Někteří lidé by rádi portovali svůj Win32 Delphi kód do Oxygenu, tak jak je. To není možné, protože přesto, že Oxygene vypadá jako Delphi, je mezi nimi tolik rozdílů, že není možné jednoduše kód rekompilovat.

Související články[editovat | editovat zdroj]

Reference[editovat | editovat zdroj]

V tomto článku byl použit překlad textu z článku Oxygene (programming language) na anglické Wikipedii.

  1. http://blogs.remobjects.com/blogs/mh/2013/04/17/p5822
  2. http://old.elementswiki.com/en/Operator_Overloading
  3. http://old.elementswiki.com/en/Built-In_Types
  4. http://old.elementswiki.com/en/Provide_Mixin-like_functionality