IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 Delphi Discussion :

type Montype =procedure of object;


Sujet :

Delphi

  1. #1
    Membre confirmé
    Avatar de Jcpan
    Inscrit en
    Août 2008
    Messages
    542
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 542
    Points : 475
    Points
    475
    Par défaut type Montype =procedure of object;
    bonjour cette source est tirée d'une autre discutions.
    Citation Envoyé par Paul TOTH Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
     
    type
     TCallBack=procedure of object;
     
    var
     obj : TObject;
     
    procedure Tform1.FreeObject;
    begin
     obj.Free;
    end;
     
    procedure TForm1.Button2Click(Sender: TObject);
    begin
     obj:=TButton.Create(nil);
     Test2(obj,FreeObject);
    end;
     
    procedure TForm1.Test2(const obj:TObject; CallBack:TCallBack);
    begin
     ShowMessage(obj.ClassName);
     CallBack;
     ShowMessage(obj.ClassName);
    end;
    Chaque fois je me dis : ça y'est j'ai saisi toutes les notions delphi , ressortent encore qlq une que je n'est jamais vu

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    type
     TCallBack=procedure of object;


    c'est quoi ce type ? quel utilité ?
    un exemple accompagné de votre explication me ferai très plaisir.

  2. #2
    Membre chevronné

    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    1 519
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 519
    Points : 2 153
    Points
    2 153
    Billets dans le blog
    1
    Par défaut
    Cette instruction permet de déclarer un nouveau type "pointeur de méthode". En fait il faut se représenter cela comme un type qui peut accueillir une méthode d'un objet.

    C'est typiquement comme cela que fonctionne les évènements. Ainsi quand tu regarde la définition du OnClick c'est de type TNotifyEvent et quelle est la déclaration du TNotifyEvent :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TNotifyEvent = procedure(Sender: TObject) of object;
    Ce qui correspond bien à ce que l'on fait quant on répond à un évènement : on écrit une méthode. Alors l'affectation ne se voit pas grâce au designer qui fait ça tout seul en "caché" lorsqu'on passe par le mode conception des fiches mais lorsqu'on fait des affectations dynamiques d'évènements et bien on affecte bien des méthodes à ce genre de propriétés.
    La FAQ - les Tutoriels - Le guide du développeur Delphi devant un problème

    Pas de sollicitations techniques par MP -

  3. #3
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 430
    Points
    28 430
    Par défaut
    Citation Envoyé par Jcpan Voir le message
    c'est quoi se type ? quel utilité ?
    un exemple accompagné de votre explication me ferai très plaisir.
    l'exemple est dans ta question

    comment passer en paramètre d'une fonction l'adresse d'une autre fonction ?
    il suffit de déclarer un type, exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    type
     TMaProcedure=procedure(parm1:integer);
     TMaFonction=function(param1:integer):string;
     
    procedure test(proc:TMaProcedure; Fonc:TMaFonction);
    ...
    la procédure "test" accepte en paramètre une procédure et une fonction dont les paramètres correspondent exactement aux types déclarés.

    reste à distinguer une procédure d'une méthode objet, en langage delphi cela se fait en précisant "of object" tout simplement
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  4. #4
    Membre éclairé Avatar de peter27x
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 029
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 029
    Points : 757
    Points
    757
    Par défaut
    Citation Envoyé par Paul TOTH Voir le message
    l'exemple est dans ta question

    comment passer en paramètre d'une fonction l'adresse d'une autre fonction ?
    il suffit de déclarer un type, exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    type
     TMaProcedure=procedure(parm1:integer);
     TMaFonction=function(param1:integer):string;
     
    procedure test(proc:TMaProcedure; Fonc:TMaFonction);
    ...
    la procédure "test" accepte en paramètre une procédure et une fonction dont les paramètres correspondent exactement aux types déclarés.

    reste à distinguer une procédure d'une méthode objet, en langage delphi cela se fait en précisant "of object" tout simplement
    Ben moi je dis les gars, vous être forts... très forts, les gars !

  5. #5
    Membre confirmé
    Avatar de Jcpan
    Inscrit en
    Août 2008
    Messages
    542
    Détails du profil
    Informations forums :
    Inscription : Août 2008
    Messages : 542
    Points : 475
    Points
    475
    Par défaut

  6. #6
    Membre chevronné

    Profil pro
    Inscrit en
    Novembre 2007
    Messages
    1 519
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 519
    Points : 2 153
    Points
    2 153
    Billets dans le blog
    1
    Par défaut
    Bon visiblement ne nous n'avons pas été très clair là-dessus

    Commençons par la déclaration :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    // pointeur de routine (procédure ou fonction)
    TMaProcedure = procedure (param1: Integer);
    TMaFonction = function (param1: Integer): String;
     
    // pointeur de méthode (procédure ou fonction)
    TMaMethodeProc = procedure (param1: Integer) of object;
    TMaMethodeFonc = function (param1: Integer): String of object;
    Dans les deux premières déclarations j'ai déclaré deux nouveaux types :
    1. un type "procédure" qui prend en paramètres un paramètre de type Integer
    2. un type "fonction" qui prend en paramètre un paramètre de type Integer et retourne un String


    De même pour les deux suivantes nous déclarons comme nouveaux types :
    1. un type "méthode" qui prend en paramètres un paramètre de type Integer
    2. un type "méthode" qui prend en paramètre un paramètre de type Integer et retourne un String


    Dès lors, tout comme le compilateur n'accepte que des entiers dans une variable entière, seules des routines ou des méthodes respectant la déclaration imposé par les types est autorisé.

    Ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    type
      TMaProcedure = procedure (param1: Integer);
     
      procedure test( ACallBack: TMaProcedure );
      procedure exemple1(param1: Integer);
      procedure exemple2(param1: String);
      function exemple3(param1: Integer): String;
     
    implementation
     
    // liste d'appels
     
    test( exemple1 ); // valide, exemple1 respecte la déclaration imposée par TMaProcedure
    test( exemple2 ); // ERREUR, TMaProcedure impose que le paramètre soit de type Integer
    test( exemple3 ); // ERREUR, TMaProcedure impose que ce soit une procédure et non une fonction
    Maintenant vous allez me dire "c'est cool mais concrètement j'en fais quoi" ? Et bien on peut en faire plusieurs chose mais le plus important à comprendre c'est que comme notre variable contient une routine (ou une méthode) et bien nous pouvons demander à exécuter cette routine (ou méthode) via la variable qui la contient :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    type
      TMaProcedure = procedure (param1: Integer);
     
      procedure test( ACallBack: TMaProcedure );
      procedure exemple1(param1: Integer);
     
    implementation
     
    procedure test( ACallBack: TMaProcedure );
    var
     Cpt: Integer;
    begin
      For Cpt := 0 to 10 Do
        ACallBack( Cpt );
    end;
     
    procedure exemple1( param1: Integer );
    begin
      ShowMessage( IntToStr( param1 ) );
    end;
     
    // appel
    test( exemple1 ); // fait apparaître 10 ShowMessage successivement avec à chaque fois la valeur du compteur pour chaque tour de boucle dans la procédure test.
    Les pointeurs de méthodes fonctionnent exactement comme les pointeurs de routines sauf que les variables ne peuvent alors contenir que des méthodes d'objets et non des routines indépendantes.
    La FAQ - les Tutoriels - Le guide du développeur Delphi devant un problème

    Pas de sollicitations techniques par MP -

  7. #7
    Membre habitué
    Profil pro
    Inscrit en
    Février 2008
    Messages
    141
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 141
    Points : 142
    Points
    142
    Par défaut
    Par exemple :

    Tu as une table qui contient des record {nom, prenom, age, taille}. Tu veux pouvoir la trier par nom, par prenom, par age, ou par taille.

    Pour la partie structure de l'algorithme, tu peux choisir n'importe quel algorithme de tri : tri à bulle, quicksort, tri par tas...

    Mais tous ces algorithmes demandent à un moment de faire des tests de la forme "x <= y". Comment faire dans notre cas? Selon le tri que l'on souhaite appliquer, on voudra en fait faire "a.nom <= b.nom", ou "a.prenom <= b.prenom", ou "a.age <= b.age", ou "a.taille <= b.taille".

    Tu pourrais écrire une fonction QuickSortParNom, qui fait applique QuickSort sur ton tableau en comparant le champ "nom" de tes articles (aux bugs et erreurs de syntaxe près) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    procedure QuickSortParNom( table : array of truc; inddebut, indfin : integer );
      var
        cle, buff : truc;
        gche, dte : integer;
    begin
      if inddebut >= indfin then exit;
     
      cle  := table[inddebut];
      gche := inddebut;
      dte  := indfin;
      i    := inddebut + 1;
      while i <= dte do
      begin
        if table[i].nom < cle.nom then 
        begin
           table[gche] := table[i];
           inc(gche);
           inc(i);
        end
        else
        begin
           buff := table[dte];
           table[dte] := table[i];
           table[i] := buff;
           dec(dte);
        end;
      end;
      table[i-1] := cle;
      QuickSortParNom( table, 0, i-2 );
      QuickSortParNom( table, i, indfin );
    end;
    puis tu pourrais écrire QuickSortParPrenom, qui aurait exactement le même code, à une ligne près : "table[i].nom < cle.nom" deviendrait "table[i].prenom < cle.prenom".
    Et pareil pour QuickSortParTaille, et pour QuickSortParAge...

    Mais c'est dommage de recopier 4 fois exactement le même code, non? Dans le code ci-dessus, on ne peut trier que par une seule clé à la fois parce que la fonction de compraison est écrite en dur dans le code ; pour la changer, il faut réécrire le code.

    Si notre fonction QuickSort pouvait prendre la fonction de comparaison en paramètre, on n'aurait à écrire le code de QuickSort qu'une seule fois. C'est justement pour cela que Delphi propose un type fonction :
    on peut définir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      TypeComparaison = function ( a,b : truc ) : boolean;
    et transformer le code de QuickSort :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    procedure QuickSort( table : array of truc; inddebut, indfin : integer; EstPlusPetitQue : TypeComparaison  );
           ...
        if EstPlusPetitQue( table[i], cle ) then 
           ...
    Et dans ce cas, la partie à écrire pour chaque tri devient juste :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    function CompParNom( a,b : truc ) : boolean;
    begin
      result := a.nom < b.nom;
    end;
     
    QuickSort( table, 0, length(table)-1, CompParNom );
     
    function CompParPrenom( a,b : truc ) : boolean;
    begin
      result := a.prennom < b.prennom;
    end;
     
    QuickSort( table, 0, length(table)-1, CompParPrenom );
     
    function CompParAge( a,b : truc ) : boolean;
    begin
      result := a.age < b.age;
    end;
     
    QuickSort( table, 0, length(table)-1, CompParAge );
     
    function CompParTaille( a,b : truc ) : boolean;
    begin
      result := a.taille < b.taille;
    end;
     
    QuickSort( table, 0, length(table)-1, CompParTaille );
    Voilà : Delphi permet de passer des fonctions en paramètre, et pour pouvoir donner un type à ces paramètres, il y a les constructeurs de type procedure et function.

    Parfois, la fonction que tu veux passser n'est pas une procédure à plat dans une unité mais une méthode d'un objet : Delphi faisait une distinction entre ces deux types -une méthode a un paramètre caché "Self", pas une procédure à plat- d'où le mot clé "of object", mais cette distinction a disparu dans Delphi 2009.

    L'intérêt de pouvoir stocker des fonctions comme des variables est que du coup, tu peux écrire des mécanisme généraux qui font appel à du code que tu ne connais pas encore.

    Le moteur de la VCL utilise intensivement ce mécanisme : quand tu écris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    monBouton.OnClick := maFonction;
    tu fais exactement ça. La VCL te fournit un objet bouton, qui gère le dessin à l'écran et la récupération des évènements souris/clavier depuis le système, mais il faut qu'il y ait un moyen pour que tu puisses lui dire "et quand je clique sur le bouton je veux que tu fasses ça".

    *LeGEC*

    PS : arf, GuyMelef a étalé sa science avant moi. Tant pis, je rajoute ma couche quand même
    *LeGEC*

  8. #8
    Rédacteur


    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    7 171
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2003
    Messages : 7 171
    Points : 15 060
    Points
    15 060
    Billets dans le blog
    1
    Par défaut
    Salut,
    Citation Envoyé par Jcpan Voir le message
    Chaque fois je me dis : ça y'est j'ai saisi toutes les notions delphi , ressortent encore qlq une que je n'est jamais vu
    Prend le temps de consulter la Faq Delphi et la page cours, par exemple celui-ci et tu peux placer celui-là dans ta todo-list

    Pratiquement toutes les notions de Delphi/Pascal sont traitées dans ces différent tutoriaux.

Discussions similaires

  1. Erreur de type "value specifies const object"
    Par alexmam15 dans le forum MFC
    Réponses: 1
    Dernier message: 18/04/2011, 22h20
  2. [VB6-OOo]createUnoService => type ou procedure non définie
    Par shaftJackson dans le forum VB 6 et antérieur
    Réponses: 8
    Dernier message: 09/02/2007, 14h31
  3. Réponses: 14
    Dernier message: 21/07/2006, 14h43
  4. Réponses: 4
    Dernier message: 04/03/2005, 17h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo