mercredi 16 janvier 2002

Types scalaires


TYPES SCALAIRES

Delphi possède de nombreux types de donnée. Le type de donnée détermine la valeur qui peut être attribuée aux variables.

Les types entiers

Type Intervalle Format/taille
Byte 0..255 non signé, 1 octet
Shortint -128..127 signé, 1 octet
Char 0..255 non signé, 1 octet
Widechar 0..65 535 non signé, 2 octets
Smallint -32 768..32 767 signé, 2 octets
Word 0..65 535 non signé, octets
Longint -2147483648.. 2147483647 signé, 4 octets
Integer -2147483648.. 2147483647 signé, 4 octets
Cardinal 0..4 294 967 295 non signé, 4 octecs
Int64 -9 223 372 036 854 775 808..9 223 372 036 854 775 807 signé, 8 octect

Les types réels

Type Intervalle Taille en octets
Real 2.9 10-39..1.7 1038 6
Double 5.0 10-324..1.7 10308 8
Real 2.9 10-39..1.7 1038 6
Extended 1.9 10-4951..1.1 104932 10
Comp -263+1..263-1 8
Currency -922337203685477.5808..
922337203685477.5807
8

Autres types

Type Valeur Taille en octets
Boolean True ou false 1
Variant varialbe 16

Le type de variant est à déconseiller lorsqu'on désire de la performance, car il s'adapte au type de donnée. Il utilisera toujours 16 octets même si sa valeur est égale à 1. Il est extrêmement lent.

jeudi 10 janvier 2002

Constante et variable


CONSTANTE ET VARIABLE

Base

Delphi fait une distinction entre constantes et variables. Une constante garde sa valeur initiale tout au long du programme, elle ne peut être modifiée. Une variable pourra durant la durée du programme changer sa valeur initiale. Les constantes et les variables doivent être déclarées avant leur utilisation. Voici un exemple de déclaration de constantes et de variables :
procedure premier;
const nul   = 0;
      code  = 'secret';
var age     : integer;
    salaire : real;
    sexe    : char;
...
Dans le cas des constantes, l'identificateur est suivi du signe "=" et de la valeur que l'on associe à la constante. Pour les variables, l'identificateur est suivi du signe ":" et du type de la variable.
Chaque déclaration de constante ou de variable se termine par un point virgule. Si plusieurs variables sont du même type, il est possible de les déclarer sous forme de liste d'identificateurs (séparés par une virgule) suivie du signe ":" et du type des variables :
var 
   age, enfants, voitures : integer;
   salaire, taille : real;

Delphi ne fait pas de distinction entre les majuscules et les minuscules pour les variables et les constantes donc si notre variable est nommée : tmpCalcul, TMPCalcul désignerait la même variable. Une telle approche peut avoir des avantages et des inconvénients. On peut faire se tromper dans le nom des variables ou constantes et ça compilera pareil. Il y aura problème si l'on souhaite utiliser notre programme, composent, dll dans un autre os et dans un autre langage de programmation.

Bloc d'instruction

Lorsque plusieurs instructions possèdent un lien entre elles, il est préfèrable de les regrouper afin de constituer un bloc d'instruction. Un bloc début par le mot «begin» et se termine par le mot «end». On doit ajouter un «;» à la fin du end; Voici un exemple

begin
   No_auto := 55;
   Age := 12;
end;

jeudi 3 janvier 2002

Premier programme


PREMIER PROGRAMME

On va créer un premier programme enfin de s'initier le plus rapidement à l'environnement de delphi.
Plaçons 4 étiquettes (labels) sur la fiche, ainsi que 2 boîtes d'édition (edit box) et 1 bouton.
Voici à quoi l'espace de travail devrait ressembler.

Comme vous pouvez le constater, les noms des composants ne sont pas très significatifs.
Sélectionnez le label1, l'inspecteur d'objet affiche automatiquement les propriétés et événements que le composant possède.

Pour changer le texte qui sera affiché par l'étiquette label1, il faut modifier sa propriété caption. Inscrivez «Nom» dans cette propriété.

Modifiez caption n'est pas tout, pour faciliter la compréhension du code, il est bien de rajouter un préfixe devant le nom du composant. Le préfixe identifiera le type de composant utilisé.

Modifiez la propriété nom (name) du label1 pour lblNom.
Inscrivez Prénom pour le label 2 (lblPrenom pour le nom du composant)

Exécution pour le bouton (cmdExecution pour le nom du composant)
Mettez le label 3 et 4 à vide (propriété caption).

Ajouter un préfixe devant le nom des composants n'est pas obligatoire, mais facilite la compréhension du code pour une utilisation ultérieure.

Je vous recommande fortement de suivre les standards que voici :
  • cmd = Bouton
  • lbl = Label
  • lst = liste
  • frm = frame
  • chk = case à cocher
  • opt = bouton radio
On commence par inscrire le standard suivi d'un nom le plus descriptif que possible. Ces standards peuvent varier en fonction de l'entreprise ou de l'institut scolaire où que l'on soit.
Voici à quoi ressemble l'espace de travail après les changements effectués



Maintenant que la conception graphique du programme est terminée, nous allons réagir à l'événement du bouton.

Lorsqu'on appuiera dessus, l'edit box du nom et du prénom s'ils ne sont pas vides iront se mettre dans les deux étiquettes du bas, leurs propriétés couleurs seront modifiées. Ne vous inquiétez pas si vous ne comprenez pas le code tout de suite, tout vous sera expliqué dans les prochains chapitres. Le but étant de vous familiariser avec edi.

Double cliqué sur le bouton afin de rentrer dans le code directement dans l'événement du bouton.

Entrez le code que voici,


ceci implique que vous avez fait les modifications des noms.
Par la suite appuyer sur la flèche verte dans la barre d'outils, le programme s'exécutera.


Entrez un nom, prénom, ensuite cliquez sur le bouton.
Admirez le résultat :)

Je vous conseille de modifier les propriétés des objets et de voir le résultat.
Vous pouvez soit le faire en mode création ou dans le code.

Dans le code, lorsque vous voulez modifier la propriété d'un objet, vous n'avez qu'à saisir le nom du composant, cliquez sur le «.» ensuite delphi vous montre les propriétés disponibles pour cet objet.

Vous choisissez celles que vous voulez, vous tapez «:=» et il vous reste plus qu'à inscrire la valeur voulue.

Exemple: lbl.color:=clwhite ceci changera la couleur de fond.

Modifier les propriétés et événements des objets, vous deviendriez meilleur plus rapidement Un bon programmeur ne doit pas craindre de faire des erreurs, vaut mieux essayer que de rester dans l'ignorance.
Code source disponible ici.

samedi 29 décembre 2001

Environnement de développement intégré


ENVIRONNEMENT DE DÉVELOPPEMENT INTÉGRÉ

L'edi (environnement de développement intégré) de delphi est divisé en 3 parties.
  • Fenêtre principale
  • Inspecteur d'objet
  • Espace de travail

Fenêtre principale



on y retrouve les barres d'outils et la palette de composants. C'est à partir de cette fenêtre qu'on choisit et dépose les composants sur notre fiche dans l'espace de travail.

L'inspecteur d'objet



L'inspecteur d'objet permet de:
  • visualiser
  • modifier
les propriétés et événements des composants en mode création.
Les propriétés et évènements varient d'un composant à l'autre.
Les propriétés correspondent aux caractéristiques, aspects, comportements d'un objet.
Explorez-les afin de les connaître d?avantage. Dans cette fenêtre, on remarque que Form1 sera affiché dans la barre de menu de l'application.
On peut aisément changer cela en modifiant la propriété caption.

Espace de travail

L'espace de travail sert à déposer les composants qui constituent notre programme.
C'est dans cette fenêtre qu'on crée la partie graphique, l'esthétique de notre programme

Éditeur de code

On écrit tout notre code dans cet éditeur. C'est la fenêtre à laquelle le programmeur passera le plus clair de son temps.


Delphi génère automatiquement le nom des composants en leur ajoutant un chiffre. Comme vous avez pu le remarquer, dans l'espace de travail la forme s'appelait form1. S'il y en avait eu une deuxième, delphi l'aurait appelé form2. Ceci s'applique pour tous les composants: bouton, liste..... On peut à tout moment changer le nom du composant enfin de lui donner un nom plus significatif.

L'edi peut s'avérer complexe au novice, mais il deviendra rapidement indispensable. Il regroupe tout ce qu'un programmeur a besoin. Il n'est plus nécessaire de disposer de plusieurs programmes séparés pour faire ce dont on a besoin.
C'est un outil très pratique, vous le découvrirez rapidement.

dimanche 23 décembre 2001

Interface


INTERFACE

Dans le chapitre précédent, nous avons vu que nous pouvons déclarer des méthodes abstraites dans une classe mère. Les méthodes peuvent ensuite être définies dans les classes enfants.

Nous pouvons créer une interface au lieu d'avoir une classe avec de nombreuses méthodes abstraites. Une interface peut ressembler à une classe mais c'en est pas une. Une interface permet de déclarer plusieurs méthodes sans les définir. Elles sont très utilisées pour les objets com.



En delphi comparativement au langage C++ on peut seulement hériter d'une seule classe. Il est impossible de faire de l'héritage multiple (image ci-dessus) avec delphi tout comme java. C'est là que les interfaces deviennent intéressantes.
La structure d'une interface ressemble à

type nomInterface = interface (interfaceAncêtre)
  ['{GUID}']
  listeMembres
end;

La longue série de lettres et de chiffres dans l'interface est un identifiant numérique.
L'interfaceAncêtre et le GUID sont facultatifs.
Il est nécessaire d'en avoir un pour pouvoir faire des «QueryInterface» et des cast dynamiques
en utilisant cette interface, il n'est pas nécessaire pour le reste.

Il faut appuyer sur «Ctrl+Shift+G» dans le l'éditeur de code pour générer un GUID.
Un exemple d'une interface

type
  IEncrypt = Interface
  ['{F26B6D20-F718-11D5-8E23-BCD4F752513A}'] //GUID
  function Encrypt(S: String; Key: Word): String;
  function Decrypt(S: String; Key: Word): String;
end;

Il est impossible de déclarer des méthodes virtual, dynamic, abstract ou override étant
donné que les interfaces n'implantent pas les méthodes. Seulement des propriétés et des
méthodes peuvent être utilisés dans les interfaces.
Code source disponible ici

lundi 17 décembre 2001

Programmation orienté objet


PROGRAMMATION ORIENTÉ OBJET

La programmation orienté objet ou plus communément appelé poo est devenu essentiel. Les gains de temps et d'argent obtenues par une telle approche ont contribué à son ascension. La poo tente de modéliser des objets de la vie courante en des objets logiciels. C'est une manière complètement différente de penser. Même si au début, c'est un peu plus complexe que la programmation procédurale, la maîtriser est à la porter de tous.

But

La poo tente de résoudre quelques lacunes de la programmation procédurale. Différents facteurs font qu'une solution orienté objet est plus adapté qu'une solution à l'ancienne. C'est évident que chaque facteur ne peut atteindre un seuil d'utilisation parfait dans une application. Il faut savoir doser chaque facteur en fonction de nos besoins présents et à venir.

Avantage de la poo

Réutilisabilité

Il arrive souvent en programmation qu'il y ait du code qui revient sans cesse de projet à projet. Habituellement, on copierait le code nécessaire dans notre projet en cours. Avec la poo, on ne copie pas le code nécessaire, on crée une classe (un genre de structure avec des fonctions et des procédures) qu'on instanciera avant de l'utiliser. Par la suite, on pourra utiliser cette classe dans tous nos autres projets et même y rajouter des fonctionnalités si on le souhaite. Plus nos classes seront réutilisables moins qu'on codera dans le futur.

Compatiblité

Il est facile de constater l'incompatibilité qu'il existe dans le domaine de l'informatique. Des logiciels conçus pour mac sont inutilisables sous PC... Palier à une telle lacune peut selon un certain seuil d'efficacité être envisageable avec la poo. Ce qu'on crée doit pouvoir fonctionner avec un maximum de classe.

Facilité d'utilisation

Étant donné que la réutilisabilité est primée en poo, on doit s'attendre que d'autre programmeur puisse un jour utilisé nos classes. Pour ne pas décourager les autres et rendre les mises à jour plus aisés, c'est important de garder nos classes simples. Une bonne documentation est des commentaires ne sont jamais de trop.

Classe

Les classes sont des types de données que le programmeur créera. Ces types de données contiennent des fonctions et des procédures qu'on désigne par des méthodes. Vous avez certainement déjà utilisé des classes sans vous en rendre compte. En créant votre interface graphique sous Delphi, cette dernière utilise de nombreuses autres classes. Plaçons une TListbox sur un formulaire. Ce code est automatiquement créé.
ListBox1: TListBox;
Dans cet exemple, TListBoxest une classe.

Objet

Un objet est tout simplement une instance, variable d'une classe. Dans l'exemple précédent, l'objet serait ListBox1

Méthode, propriété

Écrivez quelque part dans le code ListBox1 ensuite appuyé sur le . Vous verrez comme sous les illustrations ci-dessous toutes les méthodes et propriétés de la classe.

Méthodes


Propriété



Les propriétés sont les caractéristiques de la classe. Pour la classe TListBox, on a la propriété MultiSelect. Cette caractéristique permet de spécifier si on veut permettre la multi-sélection dans la liste.En assignant true à cette propriété, la liste permettra de sélection plusieurs éléments. En ajoutant items.add, on accède à une méthode qui permet d'ajouter un élément de type string dans la liste.
Un autre exemple serait une voiture. Une voiture peut avoir plusieurs caractéristiques comme : transmission, turbo, vitre électrique,vitesse. Pour les méthodes, on pourrait avoir : démarrer,rouler,arrêt.

Opération sur les classes

Utilisation

Les objets demandent des opérations additionnelles pour qu'il puisse fonctionner correctement. Lorsqu'on utilise des composés comme TListBox, TLabel... et qu'on les dépose sur notre fiche, Delphi s'occupe de certaines opérations pour nous. Ces opérations qui sont la construction et la destruction d'objet doivent être faites par le programmeur lorsque nous instancions n'importe quel objet tel que TListBox, TLabel... à l'exécution.

Construction

Lorsqu'on désire construire un objet, on doit utiliser la méthode create. Il peut arriver que cette méthode nécessite des paramètres. Cette méthode initialise les données de l'objet lors de sa création. Il est possible de surcharger un constructeur. Delphi met nos données automatiquement à zéro, si on veut que nos données soient initialisées à d'autres valeurs, on crée un constructeur.
Un modèle de constructeur pourrait ressembler à ceci
>objet := classe.constructeur[(paramètres)];

Destruction

Un destructeur sert à détruire un objet. Cet objet ne pourra plus être utilisé par la suite. Le destructeur a une syntaxe semblable à un destructeur.

objet := objet.destructeur[(parametres)];

Il est rare que l'on doive créer un destructeur car on peut le détruire en appelant la 
méthode Free. Avant d'appeler cette méthode, on devrait toujours mettre l'objet à nil puisque
que l'objet ne connaît pas les variables qui peuvent le référencer.
A partir de Delphi 5, on peut faire appel à la méthode FreeAndNil(objet). En mettant l'objet
à nil, il n'y aura pas d'erreur si on tente de détruire l'objet plusieurs fois.

Contrôle d'accès

En programmation procédurale, n'importe qui peut modifier à peu près n'importe quoi. Il n'est pas rare de chercher pourquoi une variable à une certaine valeur et de se rendre compte que dans le code que son contenu est modifié. Beaucoup d'erreurs peuvent facilement intervenir. En poo, on a vu restreindre ce type d'erreur en permettant d'avoir un certain contrôle sur le contenu d'une classe. Les données ne peuvent être modifiées que par des méthodes. L'accès aux données est ainsi indirect, leur sécurité est accrue. Delphi permet quatre types d'accès aux données.
  • Private
  • Public
  • Protected
  • Published
Nous discuterons seulement des 3 premiers dans ce chapitre. Le dernier étant réservé principalement pour les composants. Les données private et protected sont accessible à n'importe quelles méthodes qui sont dans la même unité. Nous devrions donc mettre une classe par unité, sinon l'accès aux données n'est pas vraiment sécuritaire.
Ceux qui utiliseront nos classes verront seulement ce que nous voudrons. Rien ne sert de donner accès à tout ce qui est dans la classe si seulement quelques données doivent être modifiées. Un exemple très simple pourrait être le cas d'un ordinateur. On n'a pas besoin de savoir comment il fonctionne ni comment les données s'affichent à l'écran. On a accès à une souris, clavier et on peut faire tout le travail que l'on désire. Le contrôle d'accès des données est aussi appelé encapsulation.Grâce à l'encapsulation, on cache le fonctionnement interne (implantation) de la classe.

private

Les données et les méthodes qui sont privés ne sont pas accessibles à l'extérieur d'une unité. On n'a pas besoin de savoir comment les données se transigent par le bus... pour utiliser l'ordinateur. Savoir cette information n'est pas pertinente pour utiliser l'ordinateur.

public

Le clavier, les haut-parleurs, la souris et l'écran seraient publics. Grâce à eux, on peut exécuter de nombreuses tâches. N'importe qui peut utiliser les objets ou méthodes déclarés public. Il faut bien choisir ce qu'on mettra dans cette section.

protected

Lorsqu'on overclock un ordinateur, seul quelques informations techniques sont nécessaires. Nul besoin de savoir comment l'information circule dans le processeur. Il faut ouvrir le boîtier et faire quelques modifications. Les données et méthodes protected sont seulement accessibles à la classe et ses sous-classes.
Voici un exemple pour mieux comprendre le fonctionnement des classes et de l'encapsulation des données.
 
unit unitAgenda;

interface

uses
  SysUtils;

type
  TAgenda = class
  private
    Annee:string;
  public
    procedure SetAnnee(const a:string);
    constructor  create;
end;

implementation

constructor TAgenda.create;
begin
  Annee:= DateToStr(Date);
end;

procedure TAgenda.SetAnnee(const a:string);
begin
  Annee:=a;
end;
end.

Après avoir créé notre classe, on peut l'utiliser dans un programme.

var  agenda:TAgenda;
begin
  agenda := TAgenda.Create;
  agenda.annee := 2005; //[Erreur] Unit1.pas(29): Identificateur non déclaré : 'annee'
  FreeAndNil(agenda);
end;

Dans l'exemple ci-dessus, on tente d'assigner une valeur au champ annee. Cette propriété
est privée, on ne peut directement accéder par elle. Delphi nous envoie un message d'erreur.
La bonne façon est d'employer la méthode SetAnnee.

var
  agenda:TAgenda;
begin
  agenda := TAgenda.Create;
  agenda.SetAnnee('2005');
  FreeAndNil(agenda);
end;

Héritage

Nous avons vu au début de ce chapitre, que la réutilisation est très importante. Souvent, on ne modifie que quelques lignes dans une fonction ou procédure pour qu'elle puisse fonctionner dans un nouveau programme. On doit alors tout copier et faire les modifications nécessaires. En poo de tel changement s'effectue grâce à l'héritage. Rien ne sert d'inventer la roue à chaque fois. Lorsqu'on fait du copier-coller, on oublie souvent des morceaux. L'héritage empêche de faire de telles erreurs. On peut ajouter de nouvelles fonctionnalités, fonctions, procédures à une classe existante en créant une nouvelle classe qui se basera sur la première. Je vais utiliser l'exemple classique utilisé pour expliquer l'héritage en poo. J'ai eu cet exemple en langage C++ et java.


La classe ancêtre, de base sur l'image ci-dessus est Forme. Les classes oval, rectangle et ligne sont dérivées de forme, on les surnomme classes dérivées ou classes enfants. La classes oval est l'ancêtre de cercle. Une telle approche permet de regrouper des points en commun dans une classe. Cette classe servira par la suite en a crér d'autres plus spécialisés. On peut continuer le schéma en ajoutant une classe carré. Un carré est en fait un rectangle avec 4 côtés identiques.



En programmation procédurale, on aurait eu probablement beaucoup de structure et elles auraient de nombreuses variables. Beaucoup de code aurait été redondant. L'héritage permet d'éviter la redondance et d'utiliser ce qui a déjà été créé. On peut sans cesse rendre les objets de plus en plus spécialisés.

Nous allons utiliser un exemple plus simple ensuite nous continuerons avec les formes pour des concepts plus avancés.


Le premier gameboy fonctionnait en noir et blanc. On pouvait l'ouvrir, l'éteindre et il y avait du son.



Lorsque la deuxième version sortit, les couleurs avaient apparu dans les jeux. On pouvait toujours l'ouvrir, l'éteindre et le son était encore de la partie. Rien ne sert de réécrire ce qui n'a pas changé. Faut seulement ajouter les nouvelles fonctionnalités.
Il suffit de rajouter le nom de la classe qu'on veut hériter en parenthèse à côté du mot réservé class.

[nom de class] = class(nom de class ancêtre)
La classe gameboy ressemblerait à
TGameBoy = class
 protected
   Alumer:boolean;
   Son:boolean;
 public
   procedure Ouvrir;
   procedure Fermer;
end;
Celle du gameboy color à
TGameBoyColor = class(TGameBoy)
 private
   Couleur:Integer;
 public
   procedure SetCouleur(Coul:Integer);
   function  GetCouleur:Integer;
end;

Les variables et méthodes de TGameBoy sont accessibles à la classe TGameBoyColor. Il
suffit d'instancier TGameBoyColor ensuite de taper le «.» et on verra les propriétés et
méthodes accessibles.

Si nous avions voulu ajouter, modifier des fonctionnalités aux méthodes existantes de TGameBoy, il aurait fallu les déclarer virtual.

TGameBoy = class
 protected
   Alumer:boolean;
   Son:boolean;
 public
   procedure Ouvrir;virual;
   procedure Fermer;virtual;
end;

Dans la classe TGameBoyColor, il faut ajouter le mot override; après les méthodes pour pouvoir les surcharger.

TGameBoyColor = class(TGameBoy)
 private
   Couleur:Integer;
 public
   procedure Ouvrir;virual;override;
   procedure Fermer;virtual;override;
   procedure SetCouleur(Coul:Integer);
   function  GetCouleur:Integer;
end;

Après les avoir surchargés, on a 2 possibilités, ajouter du code à celui existant ou réécrire complètement la 
méthode. Si on ajoute du code, il faut mettre le mot inherited. Dans le cas contraire, on inscrit le code qu'on désire.

procedure Open;
begin
  inherited;
  GetCouleur;
end;

Tout le code de la méthode open de la classe TGameBoy est exécuté plus le nouveau bout
de code. Nul besoin de tout recopier le code, ajouter un seul mot suffit.

Polymorphisme

Le polymorphisme permet d'appeler une méthode commune à un groupe d'objet (héritage). Nul de besoin de se soucier de la classe à appeler, le programme détermine dynamiquement quelle méthode appelée selon la méthode.

Méthode abstraite

Les méthodes abstraites sont très importantes pour profiter pleinement du polymorphisme. Le mot abstract est utilisé en Delphi pour une classe déclarée mais non défini dans une classe ancêtre. Seulement ses sous-classes la définiront. Dans l'exemple antérieur sur les formes, TForme pourrait avoir une méthode dessiner mais elle ne serait pas définie. Rectangle, Oval, ligne... auraient aussi cette méthode pleinement définie. Alors si nous créons un tableau de TForme et que nous y insérons des rectangles, carrés, cercles... En appelant la méthode dessine de TForme, on pourrait dessiner toutes les formes sans connaître d'avance si c'est un rectangle, cercle carré.

Un programme est disponible ici

Nous pouvons remarquer dans ce programme que la méthode dessine est déclarée abstract. Comme je l'ai dit, une méthode abstract doit seulement être déclarée. Les autres héritent de TForme. Elles doivent mettre le mot override à leurs méthodes dessiner, on peut ensuite les définir. Regardez ce code assez simple (j'ai tout mis dans la même unité) et essayé de le comprendre.

jeudi 11 octobre 2001

Comment fermer une application par son nom?

Comment fermer une application par son nom?
function KillApp(const sCapt: PChar) : boolean;
 var AppHandle:THandle;
begin
 AppHandle:=FindWindow(Nil, sCapt);
 Result:=PostMessage(AppHandle, WM_QUIT, 0, 0);
end;

Quand JPA rencontre ses limites, pensez à jOOQ et au MULTISET

Une seule requête, un graphe d'objets complet — ce n'est pas de la magie, c'est du SQL. La base du problème Dans le monde JPA, q...