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 :

Casts et surcharge de fonction


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut Casts et surcharge de fonction
    Bonjour tout le monde,

    J'utilise actuellement un équivalent de factory qui instancie différents types d'objets selon des conditions précises, et les retourne en les (up?)castant vers une classe dont tous ces objets héritent.
    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Class BaseObject {}
    Class SubObject1 : BaseObject {}
    Class SubObject2 : BaseObject {}
    Ce que fait la factory:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    public static BaseObject SpawnObject(String str)
    {
      if (str == "toto")
      {
         SubObject1 tutu = new SubObject1();
         return (BaseObject)tutu;
      }
      if (str == "titi")
      {
         SubObject1 tutu = new SubObject2();
         return (BaseObject)tutu;
      }
    }
    Ce que j'aimerais faire dans l'idéal est que la fonction appelant la factory (et recevant donc un BaseObject) puisse appeler une autre fonction "générique" en passant cet objet, et que la fonction appelée puisse déduire facilement ce qui est à faire (d'après les tests que j'ai fait, la surcharge ne semble pas possible car le type passé est le type retenu pour la surcharge).
    Y'aurait-il un moyen simple de faire ce que je souhaite ? Genre comme en PHP ou on peut faire ça sans souci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <?php $toto = 'uneClasse'; $tutu = new $toto(); ?>
    J'ai bien pensé à ajouter un membre String contenant le type de la classe récupéré par la reflection, mais je trouve ça malhabile.

    Merci d'avance

  2. #2
    Membre émérite

    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juin 2011
    Messages
    487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2011
    Messages : 487
    Par défaut
    Bonjour,

    J'avoue ne pas avoir tout saisi (et surtout pas l'exemple en php ), les titi toto et tutu m'embrouillent :p

    Est ce que tu ne chercherais pas quelque chose du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if(toto is SubObject1)
    	tata = toto as SubObject1;
    Mon blog sur les technos .NET et Agile -> http://blog.developpez.com/maximepalmisano/

  3. #3
    Membre Expert Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Par défaut
    Je suis pas sûr d'avoir compris. En gros, après avoir appelé ta factory et récupéré une référence de "BaseObject", tu voudrais appeler une autre méthode qui prendrait ce BaseObject en paramète et se comporterait différemment selon son type réel ?
    Un truc comme ça ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public void Bidule(BaseObject obj)
    {
      if (obj is SubObject2)
      {
        ((SubObject2)obj).Machin = Truc;
      }
      else if (obj is SubObject1)
      {
         ...
      }
    ...
    }
    Que doit faire cette méthode ? Si elle sert à initialiser l'objet, autant que ce soit la méthode factory qui le fasse. Elle peut aussi être une méthode membre abstraite de BaseObject et surchargée dans les classes filles, ce qui évite le pseudo-switch moche sur le type ci-dessus.

    Mais en tous cas, tu pourrais détailler ce que cette fameuse fonction est sensée faire, avec un exemple concret ?

    D'ailleurs, il n'est pas utile de forcer le cast. Tu peux simplement écrire "return tutu", parce qu'un upcast est implicite.

  4. #4
    Invité
    Invité(e)
    Par défaut
    L'exemple PHP permettait de voir un peu ce que je voulais faire (création de classe en dynamique à partir d'un string; en gros dans l'exemple PHP lit le contenu de la variable et l'utilise pour instancier la classe 'uneClasse').

    Sinon effectivement je pourrais faire un gros switch/case ou if/else if, mais j'aimerais éviter car c'est lourd et je suis sûr qu'on peut mieux faire

    Pour expliciter mieux mon exemple de code, j'ai trois groupes de classes. Le premier, c'est la factory qui instancie tous les objets à partir d'un string et retourne une référence dessus. Le second groupe représente les objets que je manipule (la classe générique mère, et les classes filles qui en dérivent et sont renvoyées par la factory avec l'upcasting). Enfin le troisième groupe est une seule classe qui joue un peu le rôle d'inventaire en manageant tous les objets qu'on lui passe.
    En gros, le main() passe un string à la Factory qui lui renvoie un objet upcasté (le main() ne connait pas son type et s'en fiche), puis le main envoie cet objet crée à la classe d'inventaire qui fait ce qu'elle a à faire en connaissant, elle, le type de l'objet passé (et le stock dans un des dictionnaires servant d'inventory).

    Du coup Guulh je ne vois pas trop comment je pourrais mettre en place ton histoire de surcharge des classes filles...

  5. #5
    Membre Expert Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Par défaut
    Si c'est à partir du nom complet de la classe que tu veux l'instancier, autant utiliser la réflexion (Activator.CreateInstance ) plutôt qu'un switch manuel.

    Je parlais de méthodes membres parce que ton besoin était flou, que je ne savais pas quelle était la nature du traitement que tu veux effectuer sur tes objets, et que le moyen le plus simple d'avoir un comportement qui dépend du type, c'est d'avoir une méthode membre virtuelle et de se reposer sur le polymorphisme

    Dans ce que tu décris: ton troisième groupe de classe, il a vraiment besoin de connaîte le vrai type des objets créés ? Si c'est juste pour le mettre dans un repository, récupérer le type réel via GetType ne te suffit pas ? Ou bien alors tu as explicitement un dico de SubObject1, SubObject2, ... ? Auquel cas ce ne serait pas très générique, par rapport à la (trop grande ?) souplesse que tu t'autorises/t'imposes en passant par des chaînes pour créer des types.

  6. #6
    Invité
    Invité(e)
    Par défaut
    Merci pour l'activator, je ne connaissais pas ! Je vais regarder ça de plus près...

    Sinon effectivement j'utilises des listes de classes bien précises, ce qui n'est pas très générique, mais je travail sur un nombre d'objets fini (pour information, mes listes contiennent des classes d'objets DHCP... À moins que MS, ISC et les créateurs de RFC ne bougent tout ça, ce n'est pas près de changer).
    Pour être vraiment précis, la classe de stockage gère une dizaine de listes contenant les scopes et leurs paramètres, les ranges et leurs paramètres, etc...D'où le fait qu'elle prenne un objet quelconque en entrée, déduise sa classe et trouve ou le placer dans ces listes.

  7. #7
    Invité
    Invité(e)
    Par défaut
    J'ai regardé un peu comment marche l'Activator, et soit je n'ai pas compris comment l'utiliser, soit je doute qu'il m'aide.
    Ce que je vois à l'heure actuelle, ce sont deux moyens dont un hypothétique d'arriver à mes fins (si vous voyez autre chose, je suis preneur !).
    D'une, je fais un switch/case sur une propriété (reflection, String en dur, ou GetType) pour savoir dans quel dictionnaire ajouter mon objet (du coup, le code est à mettre au niveau de la classe de stockage, et suppose que la reflection ou la fonction GetType me renvoie bien la classe réelle et non la classe d'upcast).
    De deux, je trouve un moyen dans le main() de virer l'upcast et de faire comprendre au compilo que je veux utiliser la classe réelle (fille) de l'objet et donc pouvoir passer par une surcharge de la fonction d'ajout de ma classe de stockage... (comment ça, je me prends la tête ? )

    Enfin en tout cas, merci beaucoup pour le coup de main

  8. #8
    Membre Expert Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Par défaut
    Cool, si ça a pu t'être utile

    Une précision quand même : C# est un langage typé, et bien que l'on puisse faire via réflexion un certain nombre de choses "innées" dans des langages dynamiques tels que PHP, ce n'est que rarement la solution la meilleure. En l'occurence, tu n'es pas en train de développer une librairie générique, comme par exemple une lib d'injection de dépendance qui se chargerait de créer des objets et de les exposer, à partir s'un fichier de config qui listerait les types concernés. Ici, tes types sont connus.

    D'où te viennent ces chaînes en entrée ? D'un fichier ? Du code lui-même ?

Discussions similaires

  1. surcharge de fonction
    Par BigNic dans le forum C++
    Réponses: 2
    Dernier message: 21/03/2006, 18h57
  2. API HOOK, Dump dll, Surcharge de Fonction
    Par MicroAlexx dans le forum Windows
    Réponses: 2
    Dernier message: 30/12/2005, 10h39
  3. [MFC] Surcharger des fonctions de CView
    Par Philippe320 dans le forum MFC
    Réponses: 2
    Dernier message: 22/11/2005, 21h24
  4. singleton, polymorphisme, et surcharge de fonction
    Par legend666 dans le forum C++
    Réponses: 11
    Dernier message: 14/11/2005, 09h27
  5. Surcharge de fonction d'un edit dynamique
    Par Tartar Ukid dans le forum C++Builder
    Réponses: 4
    Dernier message: 13/10/2003, 11h56

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