Oxygene (programovací jazyk)
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ý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 |
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
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
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
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
.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
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
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
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
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
Hello World
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
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
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
- 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
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
Reference
V tomto článku byl použit překlad textu z článku Oxygene (programming language) na anglické Wikipedii.
- Archivovaná kopie. blogs.remobjects.com [online]. [cit. 2015-06-24]. Dostupné v archivu pořízeném dne 2013-06-20.
- Archivovaná kopie. old.elementswiki.com [online]. [cit. 2015-06-24]. Dostupné v archivu pořízeném dne 2015-06-24.
- Archivovaná kopie. old.elementswiki.com [online]. [cit. 2015-06-24]. Dostupné v archivu pořízeném dne 2015-06-24.
- Archivovaná kopie. old.elementswiki.com [online]. [cit. 2015-06-24]. Dostupné v archivu pořízeném dne 2015-06-24.