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 :

[Débutant] Mort du héros - une exception ?


Sujet :

Langage Delphi

  1. #1
    Membre à l'essai

    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 20
    Points : 18
    Points
    18
    Par défaut [Débutant] Mort du héros - une exception ?
    Bonjour,
    Je vous présente d'abord les classes (simplifiées) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Personnage = class
      protected
        PV : integer;
    end;
     
    Monstre = class (Personnage)
    end;
     
    Heros = class (Personnage)
    end;
    Je souhaiterais pouvoir mettre quelque part chez mon Héros,

    if PV = 0 raise MortDuHeros.Create('Héros mort');
    avec MortDuHeros = class(Exception)

    Bref, quand le héros meurt, je souhaite déclencher une exception qui sera interceptée par le programme principal.
    Le hic est que j'avais pensé employer une property delphi. Mais, je n'ai pas besoin de l'aspect property pour la classe Personnage (si le monstre meurt, c'est son problème), mais seulement pour la classe Héros.

    Je patine, vraiment... Comment lanceriez-vous cette exception de façon propre ?

    Merci d'avance, jacques

  2. #2
    Membre émérite
    Avatar de Merlin
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mars 2002
    Messages
    524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information

    Informations forums :
    Inscription : Mars 2002
    Messages : 524
    Points : 2 883
    Points
    2 883
    Par défaut
    De deux choses l'une, soit tu gères des exceptions soit tu ne le fais pas..
    Voyons les deux méthodes:

    - avec exception.
    Si les points de vie PV passent à zéro le personnage meurt. C'est donc bien une caractéristique de tout personnage.
    Si il meurt, il génère une exception.
    Mais seules les exceptions du personnage héro t'intéressent...
    Donc plusieurs approchent :
    a) tu lèves l'exception dans personnage et c'est au niveau de l'objet application que tu filtres les exceptions tout simplement... si le sender n'est pas le héro tu "étouffes" l'exception et voila.
    b) dans personnage tu lèves l'exception dans une méthode protected virtual disons "JeSuisMort". Dans la classe monstre tu overrides cette méthode que tu laisses vide sans appeler inherited. Moralité le monstre ne lèveras plus d'exception..

    - sans exception
    Si seule la classe hero mérite qu'on s'intéresse à sa mort, alors effectivement ça ne sert à rien de prévoir un comportement global dans personnage pour l'annuler ensuite pour tous les descendants sauf héro...
    Une autre approche serait donc de créer un événement dans la classe personnage, événement appelé quand PV passe à zéro.
    Si l'application veut suivre la mort d'un personnage en particulier (comme le héro) il lui suffit de gérer l'événement. Si elle ne le fait pas rien ne se passe. Cette façon de faire est assez séduisante car elle est "extensible" si demain tui créés un monstre2 dont la mort doit être détectée il suffira simplement de gérer sont événement OnJeSuisMort ...

  3. #3
    Membre à l'essai

    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    Merci Merlin.

    Les solutions avec exception a) et b) me paraissent SUPER TOP (je vais les essayer).
    Pour l'instant, je m'occupe de la solution sans exception. Elle me tente beaucoup mais j'ai du mal à la mettre en oeuvre.

    Après quelques recherches, j'obtiens
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    type
      OnJesuismort = procedure (Sender:TObject) of Object;
    et pour la classe Personnage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
         onjsm : OnJesuismort;
    Dans le constructeur,
    Ensuite, dans la classe Personnage, à l'endroit ad hoc
    (lorsque PV = 0)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if (Assigned(OnJsm)) then
      OnJsm(self)
    Cela correspond ?
    Mais, ensuite, comment faire pour "gérer cet événement"? Quelles lignes écrire ? Où caser ce probable :
    if (Sender is Heros) then ... ?

    Merci d'avance, Jacques

  4. #4
    Membre émérite
    Avatar de Merlin
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Mars 2002
    Messages
    524
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information

    Informations forums :
    Inscription : Mars 2002
    Messages : 524
    Points : 2 883
    Points
    2 883
    Par défaut
    Tu peux déclarer OnJeSuisMort comme de type TNotifyEvent, ça revient au même mais c'est déjà déclaré autant s'en servir.

    Pour les déclarations :
    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
     
    type personnage  : class
     private
      procedure DojeSuisMort;
      _onjesuismort : TnotifyEvent;
     _pv : integer;
    procedure setpb(value:integer);
     public
      property PV:integer read _pv write setpv;
      property OnJeSuisMort:TnotifyEvent read _onjesuismort write _onjesuismort;
    end;
     
    procedure personnage.setpv(value:integer)
    begin
     pv=value;
     if pv<=0 then DoJesuismort;
    end;
     
    procedure personnage.DoJeSuisMort
    begin
     if assigned(_onjesuismort) then _onjesuismort(self);
    end;
    ----

    maintenant pour l'utiliser, c'est facile, imaginons Form1 qui utilise la classe, tu définiras une méthode de form1:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    procedure Form1.PersonnageMort(sender:tobject)
    begin
    if (sender is THero) then...// c'est un héro qui déclenche
    end;
    et quand tu créés le personnage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    var MonPersonnage : TPersonnage;
    begin
     MonPersonnage := THero.create;
     MonPersonnage.OnJeSuisMort := PersonnageMort;
    ...
    Et voilà

  5. #5
    Rédacteur
    Avatar de Pedro
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    5 411
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 5 411
    Points : 8 078
    Points
    8 078
    Par défaut


  6. #6
    Membre à l'essai

    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    20
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 20
    Points : 18
    Points
    18
    Par défaut
    Enchanteur, Merlin !
    La lumière commence à paraître, enfin, commence juste :

    Voici le code (juste un brin de recopiage, pour faire éventuellement un copier/coller dans delphi - j'utilise une application console)

    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
     
    uses
      SysUtils,
      Classes;
     
    type
      Personnage = class
        protected
          _PV : integer;
          _onjesuismort : TNotifyEvent;
          procedure Dojesuismort;
          procedure setpv(npv: integer);
     
        public
          property OnJesuismort:TNotifyEvent read _onjesuismort write _onjesuismort;
          property PV:integer read _pv write setpv;
      end;
     
      Heros = class (Personnage);
     
      Page = class
        procedure PersonnageMort(sender:Tobject);
      end;
     
    procedure Personnage.setpv(npv:integer);
    begin
      _PV := npv;
      if PV = 0 then DOJesuismort;
    end;
     
    procedure Personnage.Dojesuismort;
    begin
      if assigned(_onjesuismort) then _onjesuismort(self);
    end;
     
    Procedure Page.PersonnageMort(sender:TObject);
    begin
      if (sender is Heros) then writeln('Heros mort');
    end;
     
    var
      her : Heros;
     
    begin
      her := Heros.Create;
      her.OnJesuismort := Page.PersonnageMort;
      her.Free;
     
    end.
    [Enfin, ça c'était avant la correction ci-dessous]

    Mais, l'ensemble ne veut pas compiler...
    Sur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    her.OnJesuismort := Page.PersonnageMort;
    j'ai droit à
    Types incompatibles : 'TNotifyEvent' et 'Procedure'.
    (Il y a des balises pour encadrer les erreurs ? )

    Bon, après recherches, je corrige mon code fautif. Personnage mort n'était pas une méthode de classe, et du coup, pas de compilation. Enfin, bref, voici le code corrigé

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    var
      her : Heros;
      p : Page;
    begin
      p := Page.Create;
      her := Heros.Create;
      her.OnJesuismort := p.PersonnageMort;
      her.PV := 0;
      her.Free;
      readln;
    end.
    Par contre, pourquoi PersonnageMort doit-elle être une procédure appartenant à un objet ? Si j'écris :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Procedure PersonnageMort(sender:TObject);
    begin
      if (sender is Heros) then writeln('Heros mort');
    end;
     
    her.OnJesuismort := PersonnageMort;
    j'obtiens
    Types incompatibles : 'pointeur de méthode' et 'Procédure normale'
    Bigre, il y a des procédures a-normales, alors ? Qu'apporte l'objet ? Pourquoi cette procédure doit-elle être membre d'un objet ?


    Bon je clique sur Résolu, la question principale étant résolue. J'espère que le code ci-dessus pourra servir pour quelqu'un dans la même situation.

    Merci, Jacques

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 1
    Dernier message: 23/03/2009, 23h09
  2. erreur :"une exception s'est produite"
    Par leborg dans le forum ASP
    Réponses: 11
    Dernier message: 02/03/2004, 15h09
  3. [JSP] Affichage numéro de ligne d'une exception
    Par PhoneKilleR dans le forum Servlets/JSP
    Réponses: 12
    Dernier message: 23/09/2003, 14h59
  4. Réponses: 2
    Dernier message: 28/08/2003, 00h00
  5. Réponses: 3
    Dernier message: 01/11/2002, 14h30

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