Chrome: De toekomst van de Delphi taal?

Chrome: De toekomst van de Delphi taal?

Hoe zou de Delphi taal, ook wel Object Pascal genoemd, eruit zien als deze helemaal “bij” zou zijn met .NET 2.0? Generics kunnen we b.v. pas in Delphi verwachten als het .NET Framework 2.0 ondersteund gaat worden. Zou het niet aardig zijn als we alvast kunnen zien hoe dat er in Object Pascal uitziet?

Chrome is een add-in die het mogelijk maakt Object Pascal te gebruiken binnen Visual Studio (2003 en 2005) en Mono. Chrome is helemaal up-to-date met ondersteuning voor .NET 2.0 en alle leuke dingen die daar bij horen. Daarnaast heeft Chrome eigen, interessante mogelijkheden, die niet direct in een andere .NET taal te vinden zijn.

Delphi en Chrome gaan ieder een eigen weg: ze zijn niet trouw aan elkaar

Delphi en Chrome gaan ieder een eigen weg: ze zijn niet trouw aan elkaar. De code in dit artikel is daarom code die niet zal compilen in een toekomstige of huidige versie van Delphi. Het is de Object Pascal interpretatie van de makers van Chrome. Het is een geheel eigen taal.

Een nieuw project

Na de installatie van Chrome biedt Visual Studio je de mogelijkheid om nieuwe projecten te beginnen zoals je dat gewoonlijk doet.

Na het laden van de Windows Application template ziet het interface gedeelte van het gegenereerde formulier er als volgt uit:

namespace MyFirstChromeApp;

interface

uses
  System.Windows.Forms,
  System.Drawing;

type
  MainForm = class(System.Windows.Forms.Form)
  private
    components: System.ComponentModel.Container := nil;
    method InitializeComponent;
  private
  protected
    method Dispose(aDisposing: boolean); override;
  public
    constructor;
  end;

In vergelijking met een Delphi .NET project vallen drie zaken op:

  • Het namespace keyword in plaats van het unit keyword. In Chrome kunnen namespaces over meerdere units ‘spannen’. Het keyword unit bestaat in Chrome niet.
  • Het gebruik van het method keyword. Dit is een vervanger voor function en procedure. In de .NET IL is een procedure exact hetzelfde als een function zonder returntype. Vandaar dat het eigenlijk geen waarde meer heeft om onderscheid te blijven maken. Het keyword method is mijns inziens dan ook een prima keuze. Procedure en function werken overigens wel in Chrome, maar zijn bedoeld voor backward compatibility.
  • Het keyword constructor wordt gebruikt zonder naam. In .NET IL is het concept constructors met naam onbekend. In IL is een constructor een speciale method met altijd de naam .ctor. Wel kan een constructor, zoals elke method trouwens, overloaded zijn. In Chrome hoef je niet moeilijk te doen met allerlei keywords. Je declareert gewoon de method opnieuw met een andere set parameters:

constructor;
constructor (Foo : string);

Class contracts

Chrome biedt twee nieuwe taalconcepten, die je helpen de staat van een object te binden aan bepaalde regels.

  • Preconditions en Postconditions: Een precondition checkt of een bepaalde boolean conditie waar is, voordat een method wordt uitgevoerd. Als deze conditie niet waar is, treedt er een assertion op.

    method MainForm.Divide (x,y : integer) : double;
    require
      y > 0;
    begin
      Result := x / y;
    end;


    Een postcondition doet het zelfde, maar dan achteraf met het ensure keyword. Zo kun je bijvoorbeeld controleren of er echt een item bij gekomen is in je collectie.

    method MyList.Add(aItem: Object);
    begin
      // ...
      // logica om item toe te voegen
      // ...
    ensure
      Count = old Count+1;
      Contains(aItem);
    end;


  • Invariants: Soms wil je niet dat het object van je klasse in een bepaalde staat komt, ook niet als je gaat refactoren of als een andere, ‘onwetende’ programmeur met je klasse aan de gang gaat.
    Invariants zijn prima te gebruiken om bugs te voorkomen. Stel je hebt een klasse die een verkeersregelinstallatie voorstelt:

    public invariants
        not ((Autos = Groen) and (Voetgangers = Groen));


    Zodra het object in een staat komt dat Autos en Voetgangers groen is, treedt een assertion op.

Chrome biedt twee nieuwe taalconcepten die je helpen de staat van een object te binden aan bepaalde regels: pre/postconditions en invariants

Generics

De essentie van generics is dat je in een klasse een type kunt gebruiken waarvan je bij het maken van de klasse nog niet weet wat het is. Bij het declareren van de klasse moet de gebruiker dan aangeven welk type het daadwerkelijk moet worden.

TMyList = class
  public
    method Add(Data : T);
    method Next;
    method Current : T;
end;

TMyList is een eenvoudige klasse die een lijstje bijhoudt van objecten van een nog op te geven object type.  De T staat voor het onbekende type. T is conventie, maar het mag ook anders heten. Daarnaast is het mogelijk om meerdere onbekende types per klasse te hebben.

var MyElementList : TMyList;
    MyIntegerList : TMyList;
begin
  MyElementList := new TMyList;
  MyElementList.Add(new TMyElement);
  MyIntegerList.Add(12); //compile error

  MyIntegerList := new TMyList;
  MyIntegerList.Add(12);
end;

Bij de declaratie van de variabelen van het type TMyList moet er opgegeven worden welk type voor T staat. In het voorbeeld zijn dat TMyElement en integer.

Vervolgens worden alle tot voor kort onbekende T’s vervangen door het opgegeven type. Dit staat vanaf dat moment ook vast, de compiler - tijdens compile time dus - vindt het daarom niet leuk als ik iets anders in de lijst probeer te stoppen dan het opgegeven type.

Waarom dan geen lijst met objecten van de moederklasse Object? Dit lijkt makkelijk omdat je daar alles in kunt doen. Dit is echter meteen het nadeel, je hebt geen sturing meer over wat er in de lijst staat en de compiler klaagt nooit. Daarnaast moet je altijd typecasten als je objecten uit de lijst haalt. En dat is kostbaar.

Verder is het mogelijk om eisen te stellen aan het type wat de T vervangt. Dit doe je met het where keyword. Op deze manier kun je bijvoorbeeld eisen dat het type een parameterloze constructor heeft en ICompareable implementeert:

TMyOtherList = class
  where T has constructor, T is IComparable

Case

Het case statement in Chrome is wat uitgebreider dan in Delphi. Zo is het ook bruikbaar met strings:

var Data : String;
begin
    case Data of
      'abc' : DoSomething;
      'def' : DoSomethingElse;
    end;
end;

Nog leuker is het case type of statement, waarmee je kunt testen of een object van een bepaalde klasse is:

method PerformActionOnClass(aClass: MyCustomClass);
begin
  case aClass type of
    TMyXYZClass:
      TMyXYZClass(aClass).DoSomething;
    TMyOtherClass:
      TMyOtherClass(aClass).DoSomethingElse;
    Else
      raise Exception.Create('Invalid Class Reference');
  end;
end;

Voorheen was je genoodzaakt dit allemaal met if.. then statements te doen. Dit komt de leesbaarheid en de hoeveelheid regels code niet ten goede.

Conclusie

Chrome biedt een uitstekende taalomgeving binnen Visual Studio. Niet alleen heb je voordeel van het feit dat je het .NET 2.0 framework kunt gebruiken - met alle nieuwe klasses en productiviteitsverhogende features - Chrome biedt ook een aantal taaluitbreidingen waarvan ik er in dit artikel een aantal heb laten zien.

Nadelen zijn dat de documentatie niet geheel up-to-date is met de features en dat de community klein is, zodat je vaak wat langer moet zoeken om antwoorden te vinden op je vragen.

Geef feedback:

CAPTCHA image
Vul de bovenstaande code hieronder in
Verzend Commentaar