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

C# Discussion :

Polymorphisme et delegate : comment définir une signature compatible


Sujet :

C#

  1. #1
    Membre habitué

    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : Canada

    Informations forums :
    Inscription : Décembre 2005
    Messages : 26
    Points : 145
    Points
    145
    Par défaut Polymorphisme et delegate : comment définir une signature compatible
    Salut,

    Soit les classes de base Véhicule() et Moteur().
    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
    public class Moteur{
           public string Nom {get;set;}
        }
     
        public delegate void RouleHandler(Moteur moteur);
     
        public class Vehicule
        {
            public string Nom {get;set;}
     
            protected RouleHandler rouleHandler= null;
     
            public void Roule(Moteur moteur)
            {
                if (null != this.rouleHandler) 
                {
                    Console.Write("La voiture " + Nom + "roule");
                    this.rouleHandler(moteur);
                }
            }
        }
    Soit deux classes héritière de Véhicule : VehiculeAuto et VehiculeManuel (VehiculeManuel non représenté ici, mais sur le même schema que VehiculeAuto )

    ainsi que les classe héritière de Moteur : MoteurAuto et MoteurManuel

    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
      public class MoteurAutomatique : Moteur
        {
            public int TypeDeBoiteAuto { get; set; }
     
            public MoteurAutomatique()
            {
                this.TypeDeBoiteAuto = 4;
                this.Nom = "Moteur auto";
            }
     
            public MoteurAutomatique(string nom, int typeDeBoiteAuto)
            {
                this.Nom = nom;
                this.TypeDeBoiteAuto = typeDeBoiteAuto;
            }
        }
     
        public class VehiculeAuto : Vehicule
        {
            private void RouleAuto(MoteurAutomatique moteurAuto) 
            {
                //Fait quelque chose de spécifique au type moteurAuto en accédant par exemple à un attribu specifique 
                Console.WriteLine("avec une boite auto de type" + moteurAuto.TypeDeBoiteAuto.ToString());           
            }
     
            public VehiculeAuto() {
                this.rouleHandler = new RouleHandler(RouleAuto);
     
            }
        }
    Quand on appelle Roule() sur la classe de base Vehicule, on exécute un Handler définie dans les classes héritière, afin que chaque véhicule effectue un traitement adapté à son contexte.

    L'intérêt, c'est qu'à haut niveau on a la même boucle, quelque soit le type de véhicule et de moteur. Ca facilite le traitement si on a une approche de type visiteur sur 5000 items: on itère sur les tous véhicules auto avec une seule instance de moteur auto.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     foreach (Vehicule vehiculeAuto in vehiculeAutoList) 
                {
                    vehicule.Roule(moteur);
                }

    Mon problème est le suivant :

    No overload for 'RouleAuto' matches delegate 'RouleHandler'

    Je suis surpris de cette erreur de compilation car RouleAuto prend en paramètre un MoteurAuto qui est un Moteur.

    1ere question pourquoi cette erreur ? On doit respecter strictement la signature d'un délégué pour qu'il soit valide ?

    2e question : Quelle signature de méthode adopter pour que RouleHandler puisse s'exécuter sur type variés ? (approche du genre RouleX(MoteurX moteur)


    ps :ca fait un bail que je suis pas passé dans le coin et ça fait toujours plaisir de poster en français.

  2. #2
    Membre éclairé Avatar de ZaaN
    Inscrit en
    Novembre 2005
    Messages
    819
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 819
    Points : 661
    Points
    661
    Par défaut
    je sais pas,... mais ta fonction et ton delegate (RouleAuto et RouleHander) n'ont pas le meme modificateur de portée.
    Pour les details, cherche tout seul !

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par ZaaN Voir le message
    je sais pas,... mais ta fonction et ton delegate (RouleAuto et RouleHander) n'ont pas le meme modificateur de portée.
    Ca ce n'est pas un problème, mais la fonction doit matcher exactement la signature du delegate. Tu ne peux pas mettre en paramètre de RouleAuto un MoteurAutomatique, car le delegate pourrait très bien recevoir en paramètre un Moteur qui ne soit pas un MoteurAutomatique...

    Par contre je ne vois pas l'intérêt ici d'utiliser un delegate plutôt qu'une méthode virtuelle... ce que tu as fait là n'est pas du polymorphisme !

  4. #4
    Membre habitué

    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    26
    Détails du profil
    Informations personnelles :
    Âge : 43
    Localisation : Canada

    Informations forums :
    Inscription : Décembre 2005
    Messages : 26
    Points : 145
    Points
    145
    Par défaut
    Salut,

    ta fonction et ton delegate (RouleAuto et RouleHander) n'ont pas le meme modificateur de portée.
    C'est une erreur de ma part, désolé.

    la fonction doit matcher exactement la signature du delegate
    Ok ça répond à l'essentiel de ma question

    tu ne peux pas mettre en paramètre de RouleAuto un MoteurAutomatique, car le delegate pourrait très bien recevoir en paramètre un Moteur qui ne soit pas un MoteurAutomatique...
    là je te suis pas. Si j'ai une signature du type RouleAuto(MoteurAutomatique unMoteurAuto) je ne peux pas passer un Moteur en paramètre (un moteur n'est pas un moteurAuto).

    Si j 'execute Roule(unMoteurAuto), là non plus pas de problème car unMoteurAuto est de type MoteurAuto, donc un moteur.

    je ne vois pas l'intérêt ici d'utiliser un delegate plutôt qu'une méthode virtuelle...
    Bing !

    effectivement je ne suis pas obligé d'utiliser un delagate. Je pourrais utiliser une méthode virtuelle, mais j ai les même contraintes d'exactitude de signature. Code je reprends du code, avant de changer tout il me faut un gain substanciel.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     ce que tu as fait là n'est pas du polymorphisme !
    Comme tu y vas ! Vouloir traiter toutes les voitures de la même manière qu'elles soient automatiques ou manuelle ça me semble être pas mal ça.
    Mon objectif est de pour voir rajouter n types de couple véhicule + moteur si necessaires.

    Ouais dis comme ça c est pas terrible.

    Le projet réel concerne pas des voitures mais une résolution de match de foot US avec 40 ou + acteurs (blocker, quarterback, running backs, ...) , ayant chacun 2 ou 3 machines à états (de corps, de moral, de logique).

    Le but du jeu est de passer à travers tous les acteurs avec une boucle simpe du genre

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     foreach (Actor actor in actors)
     {
         foreach (Behavior behavior in actor.BehaviorList) 
         {
             behavior.stateMachine.Update(behavior.DataContext);
          }
     }
    où behavior est le couple d'une StateMachine et de ses données de travail (DataContext).
    Les données sont propres aux acteurs mais plusieurs acteurs peuvent partager la meme StateMachine...


    Au final, et pour implémenter mon approche "moteurs" visiteurs de véhicules et à cause de la contrainte d'exactitude dans la signature, je suis obligé d'utiliser un cast :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    public void RouleAuto(Moteur moteur) 
            {
                MoteurAutomatique unMoteurAuto = (MoteurAutomatique)moteur;
                //Fait quelque chose de spécifique au type moteurAuto en accédant par exemple à un attribu specifique 
                Console.WriteLine("avec une boite auto de type" + unMoteurAuto.TypeDeBoiteAuto.ToString());           
            }
    C est môche moi je trouve.

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Citation Envoyé par Nalfouille Voir le message
    là je te suis pas. Si j'ai une signature du type RouleAuto(MoteurAutomatique unMoteurAuto) je ne peux pas passer un Moteur en paramètre (un moteur n'est pas un moteurAuto).

    Si j 'execute Roule(unMoteurAuto), là non plus pas de problème car unMoteurAuto est de type MoteurAuto, donc un moteur.
    Je me suis mal exprimé. Je veux dire que puisque RouleHandler est déclaré avec un paramètre Moteur, RouleAuto (qui prend en paramètre un MoteurAuto) ne peut être affecté à ce delegate. Tout simplement parce que :
    - RouleAuto n'accepte qu'un MoteurAuto, pas un Moteur en général
    - RouleHandler est déclaré comme acceptant un Moteur, donc rien ne garantit que le paramètre passé à RouleHandler sera bien un MoteurAuto

Discussions similaires

  1. Réponses: 2
    Dernier message: 30/07/2006, 19h12
  2. Réponses: 2
    Dernier message: 29/06/2006, 13h58
  3. [DDE] Comment créer une application compatible ?
    Par Stef.web dans le forum Langage
    Réponses: 2
    Dernier message: 14/12/2005, 08h45
  4. Comment comment définir une clef primaire dans une table??
    Par nek_kro_kvlt dans le forum Bases de données
    Réponses: 4
    Dernier message: 07/02/2005, 21h06
  5. Réponses: 8
    Dernier message: 20/12/2004, 15h14

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