Accueil
Rechercher:
sur developpez.com sur les forums
Forums | Tutoriels | F.A.Q's | Participez | Hébergement | Contacts
Club Emploi Blogs   TV   Dév. Web PHP XML Python Autres 2D-3D-Jeux Sécurité Windows Linux PC Mac
Accueil Conception Java DotNET Visual Basic  C  C++ Delphi MS-Office SQL & SGBD Oracle  4D  Business Intelligence
FORUMS DELPHI F.A.Q DELPHI TUTORIELS DELPHI LIVRES COMPOSANTS SOURCES DEFI TELECHARGEZ DELPHI TV

Les possibles évolutions du langage Delphi sous Delphi 2005

Date de publication : 09/10/2004 , Date de mise a jour : 15/10/2004

Par Laurent Dardenne (home page)
 

Pour une présentation de Delphi 2005, vous pouvez consulter l'article de Pierre Castelain.
Cet article présente les évolutions du langage Delphi sous Delphi 2005.
Il s'agit bien sur de possible évolutions étant donné qu'à ce jour, début octobre 2004, le produit n'est pas encore finalisé.
Sous réserve de ma traduction de l'aide en ligne de Delphi 2005.


1. Convention d'appel INLINE
2. Déclarations imbriquées
2.1. Déclaration de types imbriqués
2.1.1. Déclarer et accèder aux classes imbriqués
2.2. Déclarations de constantes imbriquées
3. Itération sur des conteneurs et des classes
3.1. Rappel de l’instruction For
3.2. Itération sur des conteneurs
3.3. Itération sur des classes
4. Les directives de compilations
4.1. MESSAGE
4.2. REALCOMPATIBILITY
4.3. UNSAFE
4.4. NODEFINE
4.5. NOINCLUDE


1. Convention d'appel INLINE

Dans la déclaration d'une procédure ou d'une fonction, vous pouvez spécifier la nouvelle directive INLINE qui permet d’améliorer l'exécution des fonctions et des procédures. Si la fonction ou la procédure répond à certains critères, le compilateur insérera le code directement, plutôt que de produire un appel ( Call xxxx).
Elle permet d’obtenir un code plus rapide par une optimisation de l'exécution, mais aux dépens de l'espace mémoire. Cette directive dupliquant le code à chaque fois. Son comportement est proche des macro-instructions disponibles dans les langages assembleur ( elle existait déjà sous TP6 & 7 ). La directive INLINE générera toujours un fichier binaire de taille plus important. Elle est employée comme d'autres directives telle que cdecl ou safecall.

Par exemple :

procedure MyProc(x:Integer); inline; begin // ... end;
function MyFunc(y:Char) : String; inline; begin // .. end;
La directive inline est une suggestion faite au compilateur. Il n'y a aucune garantie que le compilateur duplique le code d’une routine particulière, car il existe certaines circonstances où cette directive ne peut pas être utilisé ( + de 10 cas recensés ), par exemple :

  • les routines contenant de l'assembleur.
  • les constructeurs et les destructeurs.
  • le bloc de programme principal, d'initialisation et de finalisation d'unité.
  • les routines qui utilisent des tableaux ouverts comme paramètres.
  • ...
Si vous modifiez l'implémentation d’une routine INLINE, vous provoquerez une recomplilation de toutes les unités qui l’utilisent. C'est une modification des règles traditionnelles de reconstruction qui sont déclenchées seulement par des changements de la section d'interface d'une unité. La directive de compilation {$INLINE [ON(default),OFF,AUTO]} vous offrira un contrôle plus fin des différents cas de figure.


2. Déclarations imbriquées


2.1. Déclaration de types imbriqués

Des déclarations de types peuvent être imbriquées dans une déclaration de classe. Les types imbriqués sont employés dans tout le framework .NET, et généralement dans toute Programmation Orientée Objet. Ce type de déclaration présente l’interêt de regrouper les types ‘conceptuellement associés’, et d'éviter des collisions de nom. La même syntaxe peut être désormais employée avec le compilateur Win32 de Delphi 2005.

Exemple de déclaration de types imbriqués :

type className = class [abstract | sealed] (ancestorType) memberList type DeclarationDeTypeImbriqué memberList end;
Là où DeclarationDeTypeImbriqué suit la syntaxe de déclaration de type définie d’ordinaire dans la partie de déclaration nommée Type.
Les déclarations de types imbriqués prennent fin dès la première occurance d'un élément du langage autre qu’un identifieur, par exemple, procedure , class, type, ou tous les spécificateurs de portée .
Les règles normales d'accés s'appliquent aux types imbriqués et à leurs types contenants, c’est à dire de niveau supèrieure que j’appellerai classe conteneur ) .

Un type imbriqué peut accéder à une variable d’instance (champ, propriété, ou méthode) de sa classe conteneur, mais il doit utiliser une référence d'objet pour le faire. Un type imbriqué peut accéder à des champs de classe, des propriétés de classe, et des méthodes statiques de la classe sans référence d'objet, mais dans ce cas les règles normales de visibilité de Delphi s'appliquent.
Les types imbriqués n'augmentent pas la taille de la classe conteneur. En d'autres termes, créer une instance de la classe conteneur ne crée pas par la même occasion une instance du type imbriqué. Les types imbriqués sont associés à leurs classes conteneur uniquement par le contexte de leur déclaration.


2.1.1. Déclarer et accèder aux classes imbriqués

Les exemples suivants vous indiquent comment déclarer et accéder à des champs et à des méthodes de classe imbriqués.

type TClassConteneur = class strict private myField: Integer; public type // Début de déclaration de la classe imbriquée TClassImbriquee = class public monChampImbrique: Integer; procedure ProcImbrique; end; // Fin de déclaration de la classe imbriquée procedure ProcConteneur; // Ici prend fin de déclaration du type imbriqué end;
Pour appliquer la méthode ProcImbrique d’une classe imbriquée, vous devez qualifier son nom avec le nom de la classe conteneur.

Par exemple :

procedure TClassConteneur.TClassImbriquee.innerProc; begin ... end;
Pour accéder aux membres du type imbriqué, employez la notation habituelle ( notation pointée : Classe.Membre). Par exemple :

var x: TClassConteneur; y: TClassConteneur.TClassImbriquee; begin x := TClassConteneur.Create; x.ProcConteneur; ... y := TClassConteneur.TClassImbriquee.Create; y.ProcImbrique;

2.2. Déclarations de constantes imbriquées

Des constantes peuvent être déclarées dans des types de classe de la même manière que la section type imbriqués.
Les sections constante sont terminées de la même maniére que les sections de type imbriquées.

les constantes typées ne sont pas supportées, vous ne pouvez donc pas déclarer des constantes imbriqués tels que Currency, ou TDateTime.
Les constantes imbriquées peuvent être de n'importe quel type simple : ordinaux et sous-ensemble ordinaux, énumération, String et Real .

Exemple de code de déclaration de constantes imbriquées :

type TMyClass = class const x = 12; y = TMyClass.x + 23; procedure Hello; private const s = 'A string constant'; end; begin writeln(TMyClass.y); // Writes the value of y, 35. end.

3. Itération sur des conteneurs et des classes


3.1. Rappel de l’instruction For

Une instruction For, à la différence d'une instruction Repeat ou While, exige que vous indiquiez explicitement le nombre d'itérations souhaitée. La syntaxe d’une instruction FOR est soit :

for compteur := Valeurinitiale to ValeurFinale do instructions
soit :

for compteur := Valeurinitiale downto ValeurFinale do instructions
où :

  • compteur est une variable locale (declarée dans le bloc contenant l’instruction for) de type ordinal, sans aucun qualifificateur.
  • ValeurInitiale et ValeurFinale sont des expressions compatible avec une assignation de compteur ( type scalaire).
  • Instructions est une instruction simple ou structurée qui ne modifie pas la valeur du compteur.

3.2. Itération sur des conteneurs

Delphi 2005 supporte, pour .NET et Win32, l'itération sur des éléments d’une collection (iteration over containers). Les itérations de conteneur suivantes sont reconnues par le compilateur :

  • for Element in ArrayExpression do Instruction;
  • for Element in StringExpression do Instruction;
  • for Element in SetExpression do Instruction;
  • for Element in CollectionExpression do Instruction;
Le type de la variable d'itération doit correspondre au type contenu dans le conteneur. Pour chaque itération de la boucle, la variable d'itération pointe sur le membre courant de la collection. Comme avec les boucles classique, la variable d'itération doit être déclarée dans le même bloc que pour l’instruction.
La variable d'itération ne peut pas être modifiée dans la boucle. Ceci inclut l’assignation, et passage de paramétre à un paramètre de var d'une procédure. Procéder ainsi aura comme conséquence une erreur lors de la compilation.
Les expressions de tableau peuvent être de type simple ou multi-dimensionnelle, de longueur fixe, ou dynamique. Le tableau est parcouru dans l'ordre croissant, commençant à partir de l’indice de limite inférieure et finissant à l’indice max du tableau.

L’exemple de code ci-dessous parcourt les différents types de tableaux :

type TIntArray = array[0..9] of Integer; TGenericIntArray = array of Integer; var IArray1: array[0..9] of Integer = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); IArray2: array[1..10] of Integer = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10); IArray3: array[1..2] of TIntArray = ((11, 12, 13, 14, 15, 16, 17, 18, 19, 20), (21, 22, 23, 24, 25, 26, 27, 28, 29, 30)); MultiDimTemp: TIntArray; IDynArray: TGenericIntArray; I: Integer; begin for I in IArray1 do begin // Fait qq chose avec I... end; // L'indexation commence à 1, la limite de rangée inférieure. for I in IArray2 do begin // Fait qq chose avec I... end; // Itération sur un tableau multi-dimensionnel for MultiDimTemp in IArray3 do // indexation 1..2 for I in MultiDimTemp do // indexation 0..9 begin // Fait qq chose avec I... end; // Itération sur un tableau dynamique IDynArray := IArray1; for I in IDynArray do begin // Fait qq chose avec I... end;
Le code suivant concerne l’itération sur des expressions de type chaîne ( String ) :

var C: Char; S1, S2: String; Counter: Integer; OS1, OS2: ShortString; AC: AnsiChar; begin S1 := 'Now is the time for all good men to come to the aid of their country.'; S2 := ''; for C in S1 do S2 := S2 + C; if S1 = S2 then WriteLn('SUCCESS #1'); else WriteLn('FAIL #1'); OS1 := 'When in the course of human events it becomes necessary to dissolve...'; OS2 := ''; for AC in OS1 do OS2 := OS2 + AC; if OS1 = OS2 then WriteLn('SUCCESS #2'); else WriteLn('FAIL #2'); end.
Le code suivant concerne l’itération sur des expressions de type ensemble ( Set ) :

type TMyThing = (one, two, three); TMySet = set of TMyThing; TCharSet = set of Char; var MySet: TMySet; MyThing: TMyThing; CharSet: TCharSet; {$IF DEFINED(CLR)} // Indique si on compile pour DOT NET C: AnsiChar; {$ELSE} C: Char; {$IFEND} begin MySet := [one, two, three]; for MyThing in MySet do begin // Fait qq chose avec MyThing... end; CharSet := [#0..#255]; for C in CharSet do begin // Fait qq chose avec C... end; end.

3.3. Itération sur des classes

Pour utiliser la construction de boucle for-in sur une classe, la classe doit implémenter un pattern de collection imposé (prescribed collection pattern). Un type qui implémente le pattern de collection doit avoir les attributs suivants :

  • La classe doit posséder une méthode publique d'instance appelée GetEnumerator(). La méthode GetEnumerator() doit renvoyer une classe, une interface, ou un type record.
  • La classe, l'interface, ou le record renvoyé par GetEnumerator() doit contenir une méthode d'instance publique appelée MoveNext(). La méthode MoveNext() doit renvoyer un booléen.
  • La classe, l'interface, ou le record renvoyé par GetEnumerator() doit contenir une propriété publique en lecture seule appelée Current. Le type de la propriété Current doit être du même type que celui contenu dans la collection.
Si le type de l’énumérateur retourné par la méthode GetEnumerator() implémente l'interface IDisposable, le compilateur appellera la méthode Dispose du type lorsque la boucle se terminera.
Le code suivant concerne l’itération sur un conteneur 'énumérable' sous Delphi 2005.

type TMyIntArray = array of Integer; TMyEnumerator = class Values: TMyIntArray; Indice: Integer; public constructor Create; function GetCurrent: Integer; function MoveNext: Boolean; property Current: Integer read GetCurrent; end; TMyContainer = class public function GetEnumerator: TMyEnumerator; end; constructor TMyEnumerator.Create; begin inherited Create; Values := TMyIntArray.Create(100, 200, 300); Indice := -1; end; function TMyEnumerator.MoveNext: Boolean; begin if Indice < High(Values) then begin Inc(Indice); Result := True; end else Result := False; end; function TMyEnumerator.GetCurrent: Integer; begin Result := Values[Indice]; end; function TMyContainer.GetEnumerator: TMyThing; begin Result := TMyEnumerator.Create; end; var MyContainer: TMyContainer; I: Integer; Counter: Integer; begin MyContainer := TMyContainer.Create; Counter := 0; for I in MyContainer do Inc(Counter, I); WriteLn('Counter = ', Counter); end.
Les classes suivantes et leurs descendants supportent la syntaxe For-in:

  • TList
  • TCollection
  • TStrings
  • TInterfaceList
  • TComponent
  • TMenuItem
  • TCustomActionList
  • TFields
  • TListItems
  • TTreeNodes
  • TToolBar

4. Les directives de compilations


4.1. MESSAGE

Syntaxe: {$MESSAGE HINT|WARN|ERROR|FATAL 'texte' }
La directive MESSAGE permet au code source d'émettre des conseils, des avertissements, et des erreurs comme le fait le compilateur . C'est une directive semblable à #emit ou pragma warn du C et C++. Le type de message (HINT, WARN, ERROR, ou FATAL) est optionnel. Si aucun type de message n'est indiqué, celui par défaut est HINT. Le texte doit être délimité par de simples quotes.
Exemples :

{$MESSAGE 'Boo!'} émet un conseil (hint) {$Message Hint 'Feed the cats'} émet un conseil (hint) {$messaGe Warn 'Looks like rain.'} émet un avertissement ( warning ) {$Message Error 'Not implemented'} émet une erreur,la compilation continue {$Message Fatal 'Bang. Yer dead.'} émits une erreur,la compilation prend fin

4.2. REALCOMPATIBILITY

Notez que l'utilisation du type Real48 n'est plus recommandé (deprecated) sous .NET. Préférez dans la plupart des cas le type double .


4.3. UNSAFE

Syntaxe:

{$UNSAFECODE ON} ou {$UNSAFECODE OFF}
Spécifique à la plateforme Dot Net.
La directive UNSAFECODE indique si le mot-clé unsafe est accepté par le compilateur. Avec {$UNSAFECODE ON}, vous pouvez identifier des procédures et des fonctions avec le mot-clé unsafe, par exemple :

procedure unsafeProc; unsafe; begin end;
Cette directive est utile seulement en .NET ( en Win32 est elle ignorée ). Unsafe signifie que le code sera compilé en non managé.


4.4. NODEFINE

Syntaxe:

{$NODEFINE Identifieur}
La directive NODEFINE empêche le symbole indiqué d'être inclus dans le fichier d'en-tête généré pour le C++, tout en permettant la génération d'information dans le fichier OBJ.
Quand vous employez NODEFINE, il est de votre responsabilité de définir n'importe quels types nécessaires avec HPPEMIT.
Par exemple :

type Temperature = type double; {$NODEFINE Temperature} {$HPPEMIT 'typedef double Temperature'}

4.5. NOINCLUDE

Syntaxe:

{$NOINCLUDE NomDeFichier}
La directive NOINCLUDE empêche le fichier indiqué d'être inclus dans les fichiers d'en-tête produits pour le C++.
Par exemple, {#$$NOINCLUDE>Unit1} enlève #include Unit1.



Ce document est issu de http://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.

Responsables bénévoles de la rubrique Delphi : NoisetteProd et Pedro - Contacter par EMail :
Vos questions techniques : forum d'entraide Delphi - Publiez vos articles, tutoriels et cours
et rejoignez-nous dans l'équipe de rédaction du club d'entraide des développeurs francophones
Nous contacter - Copyright © 2000-2008 www.developpez.com - Legal informations.