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

Langage Delphi Discussion :

Classe générique et héritage


Sujet :

Langage Delphi

  1. #1
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2008
    Messages : 26
    Points : 12
    Points
    12
    Par défaut Classe générique et héritage
    Salut salut, je voudrais une petite précision concernant les classes génériques en Delphi. Je voudrais savoir s'il était possible de définir une classe qui hériterait d'une classe générique ayant en paramètre la classe que je suis en train de définir. En d'autres termes, faire une sorte de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Myclass = class(MyClassGeneric<MyClass>)
    Merci, a toute !

  2. #2
    Membre éclairé Avatar de Kaféine
    Homme Profil pro
    Inscrit en
    Avril 2007
    Messages
    569
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 569
    Points : 736
    Points
    736
    Par défaut
    Je prend mes responsabilité et je dit oui c'est possible !

    en tout cas ceci compile:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
      TTest<T> = class
     
      end;
     
      TSalut = class(TTest<TSalut>)
      private
     
      end;

  3. #3
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2008
    Messages : 26
    Points : 12
    Points
    12
    Par défaut
    Salut salut, ok merci de la réponse, j'aurais du préciser un peu plus.
    En fait, je voudrais appeler
    avec create un constructeur de la classe T.

    Apparement, avec la clause constructor, cela ne marche pas (d'où ma première question car je pensais que cela ne fonctionnait pas du tout même avec aucune clause). Merci.

  4. #4
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Peux-tu donner ton code complet (avec tes constructeurs, leurs appels, et la clause constructor) ?

  5. #5
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2008
    Messages : 26
    Points : 12
    Points
    12
    Par défaut
    Salut, voila voila
    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
     
    type
        TGenericClass<T : constructor> = class
     
          protected
            constructor create();
     
          public
            class function CreateInstance() : T; static;
     
        end;
    ///////////////////////////////////////////////////////////////////
        TMyClass = class(TGenericClass<TMyClass>)
          public
            constructor create;
        end;
    //////////////////////////////////////////////////////////////////
    constructor TMyClass.create();
      begin
        Write('Je construis');
      end;
    ////////////////////////////////////////////////////////////////
    constructor TGenericClass<T>.create();
      begin
        Writeln('Generic constructor called');
      end;
    Ce que je cherche à faire....

  6. #6
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Hum, oui, je vois où est le problème. Mais je ne vois pas de solution.
    Ce n'est même pas un bug à proprement parler, plutôt une "limitation" des génériques en Delphi

    Parce qu'en fait, il faut savoir que le Delphi est compilé en une passe, c'est-à-dire que l'analyse du code se fait linéairement du début à la fin, sans jamais revenir en arrière.
    Donc, au moment où il compile le (TGenericClass<TMyClass>), il reconnaît TGenericClass comme acceptant un paramètre classe avec constructor, et reconnaît que TMyClass est bien une classe. Mais à ce moment, il n'a pas encore "vu" la définition du constructor Create de TMyClass. Donc à ce moment, TMyClass ne vérifie pas la contrainte constructor. Il ne peut donc pas compiler.

    Malheureusement, cette limitation est incontournable, car quelque soit la façon dont on s'y prend, on aura toujours une dépendance circulaire entre "je veux hériter de TGenericClass<TMyClass>" et "avant ça, je dois satisfaire la contrainte constructor".

    Le mieux serait de remonter cette limitation à Embarcadero dans QC, mais pour avoir écrit un compilateur Delphi, j'émets déjà des doutes sérieux quant à l'existence d'une solution, côté compilateur.

  7. #7
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2008
    Messages : 26
    Points : 12
    Points
    12
    Par défaut
    Salut salut, oui je me doutais que c'était une restriction du langage, donc je demandais si quelqu'un avait un moyen de contourner ca. Je vais envoyer un message a Embarcadero alors et je vous tiens au courant. Merci !

  8. #8
    Aos
    Aos est déconnecté
    Membre habitué

    Profil pro
    Inscrit en
    Janvier 2006
    Messages
    189
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 189
    Points : 187
    Points
    187
    Par défaut
    Je sais que ça peut paraitre trollesque, mais déja que les génériques sont arrivés tres tard chez Delphi, c'est quand meme le pompon qu'on puisse pas faire ça...

    Desolé pour la dérive

  9. #9
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Il est vrai qu'on pourrait imaginer ne vérifier les contraintes que lorsque "le type est complètement défini".

    Mais tout ça n'est pas simple, et cette limitation est intrinsèque au fait que le Delphi est un langage à compilation en une passe. On ne peut pas vraiment le reprocher à CodeGear.

  10. #10
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2008
    Messages : 26
    Points : 12
    Points
    12
    Par défaut
    Salut salut, voila, j'ai fait remonté le problème dans QC et j'ai posté également sur le forum d'embarcadero. La réponse est qu'apparement ce serait un "bug" (c'est ce qu'ils m'ont dit sur le forum, en attendant que le rapport remonte dans QC) et un moyen de contourner le problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    type
    TGenericClass<T : class> = class
    class function CreateInstance() : T; virtual; abstract;
    end;
     
    TMyClass = class(TGenericClass<TMyClass>)
    class function CreateInstance() : TMyClass; override;
    end;
    Voila, merci !

  11. #11
    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 : 55
    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 448
    Points
    28 448
    Par défaut
    si je comprend bien les génériques, ce correctif leur fait perdre tout leur intérêt

  12. #12
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2008
    Messages : 26
    Points : 12
    Points
    12
    Par défaut
    Oui ^^ Mais en attendant il n'y a que ça qui marche, espérons que Embarcadero apporte la solution rapidement

  13. #13
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2008
    Messages : 26
    Points : 12
    Points
    12
    Par défaut
    Salut, salut.
    Voila j'ai un autre soucis.
    Tout d'abord, le code:
    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
     
    type
    TGenericClass<T : class> = class
    public
    class function CreateInstance() : T; virtual; abstract;
    class procedure Kill(); virtual;
    end;
     
    TMyClass = class(TGenericClass<TMyClass>)
    public
    class function CreateInstance() : TMyClass; override;
    procedure Test();
    end;
     
    ///////////////////////////////////
    Main.pas
    /////////////////////////////////
    procedure main();
    var
     Test1 : TMyClass;
    begin
     
      Test1:= TMyClass.CreateInstance(); //Ici ca marche
      Test1.Kill(); //Ici erreur interne à la compilation
    end
    Alors voila, ma question c'est peut-on appeler une méthode d'une classe générique mère ?
    Thx.

  14. #14
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    Et si tu écris :
    au lieu de
    Ca fait aussi une erreur interne ?

  15. #15
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2008
    Messages : 26
    Points : 12
    Points
    12
    Par défaut
    Salut, ouais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DCC Erreur fatale F2084 Erreur interne : AV21B2E436-R0000000C-0

  16. #16
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2008
    Messages : 26
    Points : 12
    Points
    12
    Par défaut
    Salut salut, bon j'ai résolu le problème en appelant la classe mère directement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    TGenericClass<TMyClass>.Kill;
    Mais maintenant j'ai un autre soucis qui n'a pas de rapport avec le sujet, mais pour éviter de recréer un post, je demande ici.

    En gros, j'ai réalisé un bind d'une lib C vers Delphi. Toutes les fonctions sont exécutés sans trop de soucis, seulement, je viens de remarquer que les string que je passe en paramètre ne sont pas correctement passés à la DLL.
    Exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    //DLL
    void display(const char* mystring);
    //Delphi
    procedure display(mystring : string); cdecl; external 'mydll.dll' name 'display'
     
    //Appel
    display('Ahahaha')
    Ici seulement le premier A est passé à la dll. Alors je voulais savoir si le problème se résout en recompilant la dll avec le compilateur de borland ou si je peux le résoudre dans mon appli ? (ouais pas trop envie de recompiler des libs...)

    Thx.

  17. #17
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 154
    Points
    10 154
    Par défaut
    char * en C c'est PAnsiChar en Delphi, pas string !

  18. #18
    Membre à l'essai
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2008
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2008
    Messages : 26
    Points : 12
    Points
    12
    Par défaut
    Ok thanks. Je pensais que const PChar fonctionnait pas en delphi vu l'extreme rigueur sur les types et le fait que les pointeurs puissent pas être utilisés comme des tableaux. Ca marche maintenant thx. Je suppose alors que wchar_t c'est un PWideChar ?

Discussions similaires

  1. [c#] Héritage d'interface et classe générique
    Par NeoKript dans le forum C#
    Réponses: 2
    Dernier message: 26/06/2011, 11h40
  2. Réponses: 3
    Dernier message: 05/10/2006, 17h15
  3. [C# 2.0] Un exemple de classe générique qui ne compile pas.
    Par Pierre8r dans le forum Windows Forms
    Réponses: 4
    Dernier message: 31/05/2006, 11h11
  4. [C#][ADO] Classe Générique ADO
    Par tscoops dans le forum Accès aux données
    Réponses: 2
    Dernier message: 15/11/2005, 14h21
  5. [Generics] Classe générique
    Par norkius dans le forum Langage
    Réponses: 4
    Dernier message: 29/10/2004, 15h57

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