De quel fils est issus cet objet ?

a marqué ce sujet comme résolu.

Bonjour,
J’ai une classe qui possède plusieurs classes filles. Dans une autre classe, je reçois un objet fils que je stocke dans une variable de la classe mère. J’aimerai savoir s’il y a un moyen de connaître la véritable classe de l’objet.

Merci d’avance,
Dark Patate

+0 -0

après, je suis pas si sûr que ça soit utile. Un exemple dans ton code permettrait de t’aider.

Souvent, si tu as besoin de retrouver la classe exacte c’est soit que tu vas chercher un pattern précis (visiteur) soit que tu es en train de faire les choses à l’envers.

Si tu peux poster un morceau de code (et un cas d’utilisation moins abstrait que "j’ai un fils avec un parent dans le grnad parent…) on pourra t’aider à comprendre. La POO c’est pas facile, faut de l’entraînement.

J’ai même pas l’impression que le pattern visiteur ait besoin de ça.
Devoir connaitre le type exact d’un objet indique une mauvaise conception objet à l’origine car cela contredit un des principes objet qui est le principe de substitution :

https://fr.m.wikipedia.org/wiki/Principe_de_substitution_de_Liskov

Un cas typique de violation du LSP peut être facilement détecté lors de l’utilisation de l’opérateur de détection du type de donnée pour conditionner un comportement en fonction du type de l’objet. Par exemple typeof en C ou C++, isinstance en Python, instanceof en Java.

En gros, je fais un jeu avec Unity. Et dans la méthode IHM je récupère l’objet actuellement sélectionné par l’utilisateur dans un objet de type classe mère. Cet objet peut être de type bâtiment ou unité (classes filles).

Donc dans la méthode d’IHM, j’ai besoin de savoir de quels fils il retourne pour adapter les données à l’écran.

J’ai l’habitude de la POO avec C++, j’en ai fait plusieurs années. Le C# j’ai commencé l’an dernier au boulot, et je fais pas vraiment de la POO très poussée donc je suis un peut rouillé, surtout sur le C#. Je réfléchis comme en C++ (même si pour le coup, je sais plus comment j’aurais fait en C++ pour trouver la classe fille).

Exemple de code :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
private void DrawOrderBarContent()
    {
        // Action communes        
        orderBarSummaryImage.GetComponent<InterfaceElement>().SetToolTipText(I18N.getString(player.SelectedObject.toolTip));
        if(player.SelectedObject is Building)
        {
            // Action pour les bâtiments
        }
        else if (player.SelectedObject is Unit)
        {
            // Actions pour les unitées
        }
    //...    

PS : en cherchant avec GetType après, j’ai vu qu’il existait le mot-clef is

+0 -0

Quel serait le problème avec :

1
2
3
4
5
private void DrawOrderBarContent()
    {
        orderBarSummaryImage.GetComponent<InterfaceElement>().SetToolTipText(I18N.getString(player.SelectedObject.toolTip));
        player.SelectedObject.action()
    //...    

?

+0 -0

C# 7 permet de faire des switch sur des types : pattern matching avec C# 7. Mais je ne suis pas persuadé que Unity supporte C# 7.

Sinon je ne suis pas trop fan des approches utilisant l’introspection, je préfère largement une approche comme celle de victor juste au dessus.

Ou alors, Unity te permet d’associer des tags à tes objets de type GameObject. Je trouve que c’est une meilleure approche pour différencier tes deux types d’objets.

Si je comprends bien ta solution @victor : je déclare une fonction action dans ma classe mère et que j’implémente différemment dans mes deux classes filles ?

Mais dans mon cas j’ai des action qui doivent être exécuter uniquement par la classe appelante, pour savoir quoi faire. Et je pense que tout passer en paramètre soit pas la solution la plus optimale. Car au moindre changement, je dois revoir les paramètres de la méthode. Voilà ce que je fais pour le moment :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
if(player.SelectedObject is Building)
{
    orderBarSummaryButton1.GetComponent<InterfaceElement>().SetToolTipText(I18N.getString("destroy"));
    orderBarSummaryButton2.GetComponent<InterfaceElement>().SetToolTipText(I18N.getString("rallying_point"));
}
else if (player.SelectedObject is Unit)
{
    orderBarSummaryButton1.GetComponent<InterfaceElement>().SetToolTipText(I18N.getString("demobilise"));
    orderBarSummaryButton2.GetComponent<InterfaceElement>().SetToolTipText("");
}

Je fais juste un changement de libellé.

Après, si vous me dite que ce n’est pas correcte niveau POO de discriminer sur le type d’objet. Je veux bien utiliser la bonne méthode. J’aime beaucoup la POO, et j’essaye de respecter autant que faire ce peu les normes :)

@GaaH : Faut que je regarde comment marche les tag, je ne les ai jamais utilisé.

+0 -0

Je sais pas pourquoi ça me semble évident, peut-être que je rate un truc, voici ce que je propose :

1
2
orderBarSummaryButton1.GetComponent<InterfaceElement>().SetToolTipText(player.SelectedObject.GetBtn1String());
orderBarSummaryButton2.GetComponent<InterfaceElement>().SetToolTipText(player.SelectedObject.GetBtn2String());
+0 -0

Hum, je pense que je me suis focalisé sur le fait de détecter le type et du coup, comme les chevaux, j’ai des œillères et je vois pas les évidences.

Et en plus ta solution est plus propre que de mettre mes strings en plein milieu d’une méthode qcq, c’est plus ordonné.

Je pensais pas que j’avais perdu mes automatismes de POO si rapidement !

Merci encore !

+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte