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 :

Question héritage sur plusieurs niveaux


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 197
    Billets dans le blog
    1
    Par défaut Question héritage sur plusieurs niveaux
    Bonjour,

    J'ai une question par rapport à un souci d'héritage...

    J'ai les classes et interfaces suivantes :

    Code csharp : 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
     
    public interface IMachin
    {
         public void FaitUnTruc();
    }
     
    public class codeType : IMachin
    {
         protected int id;
         public void FaitUnTruc()
         {
             Console.WriteLine("truc");
         }
    }
     
    public class nomType : codeType
    {
         public string nom;
    }
     
    public class prenomType : nomType
    {
         public string prenom;
    }

    Et une autre classe quelconque :
    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public class Bidulle
    {
        public prenomType MonObjectAvecUnPrenom;
    }

    Et enfin plus loin dans le code j'ai ça :
    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        Bidulle oBidille = new();
        codeType o = oBidille.MonObjectAvecUnPrenom; // <= Ca plante ici en disant qu'une conversion implicite de prenomType vers codeType est impossible. Pourquoi ???

  2. #2
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 063
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 063
    Par défaut
    Hello,

    Je ne connais pas le C# mais ayant des connaissances en POO, je suis surpris que ce genre de chose passe...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class codeType : IMachin
    {
         protected int id;
         public void FaitUnTruc()
         {
             Console.WriteLine("truc");
         }
    }
     
    public class codeType : IMachin
    {
         public int id; }
    Comment le compilateur choisit ? Tu voulais faire quoi concrètement ?

    Je pense que c'est cela qui empêche le reste de fonctionner, car ta classe prenomType hérite de nomType qui hérite de codeType.

    Pour la suite tu voulais peut-être dire ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Bidulle oBidulle = new Bidulle();
    codeType o = (codeType)oBidulle.MonObjectAvecUnPrenom;
    en utilisant un cast tu assures le type d'objet en retour, mais ça c'est si tes héritages sont bien cohérents.

  3. #3
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 197
    Billets dans le blog
    1
    Par défaut
    Bonjour fred1599,

    Merci pour ta réponse

    La première anomalie que tu mentionnes, c'est une coquille de ma part.
    Il n'y a qu'une seule classe codeType en effet, la seconde il faut l'ignorer.

    Quant à new() il s'agit d'un opérateur qui permet de raccourcir l'appel du constructeur, introduit il y a quelques versions dans C#
    https://learn.microsoft.com/fr-fr/do...s/new-operator
    => Ca permet d'appeler le contructeur de la classe qui correspond au type d'objet qu'on est en train d'instancier. Ca allège le code, puisque ça sert à rien de nommer explicitement le type de l'objet déclaré si on connait déjà le type dans lequel on va stocker l'instance.

    Bref, pour en revenir au sujet, oui, avec un cast explicite ça marche.
    Perso je préfère utiliser "as" plutpôt que (type) ça évite de créer une nouvelle instance.

    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Bidulle oBidille = new();
    codeType o = oBidille.MonObjectAvecUnPrenom as codeType;

    Sauf que MonObjectAvecUnPrenom étant de type prenomType qui hérite de nomType qui hérite de codeType, je suis surpris de devoir caster explicitement. Si o était un nomType il n'y avait aucun cast explicite à faire.

    Et même :
    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Bidulle oBidille = new();
    nomType n = oBidille.MonObjectAvecUnPrenom as codeType;
    codeType o = n;
    => A priori ça marche sans caster quoi que ce soit explicitement.

    Ou alors je suis à la rue complet ?

  4. #4
    Expert confirmé
    Avatar de fred1599
    Homme Profil pro
    Lead Dev Python
    Inscrit en
    Juillet 2006
    Messages
    4 063
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations professionnelles :
    Activité : Lead Dev Python
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Juillet 2006
    Messages : 4 063
    Par défaut
    Ok, je te fais confiance pour le C#

    Mais new à mon sens n'assure pas le type réel de l'objet à la compilation, ou je me trompe ?

    Par contre je vois cela dans la documentation,

    Citation Envoyé par doc
    L’opérateur as convertit explicitement le résultat d’une expression en un type de valeur de référence ou nullable. Si la conversion est impossible, l’opérateur as renvoie null.
    Du coup je pense qu'il faut prendre en compte la valeur null car il semble que cet opérateur n'échoue jamais...

  5. #5
    r0d
    r0d est déconnecté
    Membre expérimenté

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    4 294
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Août 2004
    Messages : 4 294
    Billets dans le blog
    2
    Par défaut
    J'ai du mal à cerner le problème, mais si ça peut aider, le code suivant est valide :
    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
    public class A{}
     
    public class B : A {}
     
    public class C : B {}
     
    public class D
    {
        public C TheC;
    }
     
    public class TheProgram
    {
        public static void Main(string[] args)
        {
            D d = new();
            A a = d.TheC;
        }
    }
    Le up cast (fils -> parent) ne pose pas de problème dans les langages orientés objets inclusifs (la classe mère est incluse dans la classe fille). Mais j'ai l'impression que toi tu essaies de faire un down cast (parent -> fils), ce qui est problématique pour tout un tas de raisons (et qui selon moi devrait être totalement interdit mais c'est un long débat) et cache en général un souci de conception.

  6. #6
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Par rapport au code proposé je ne vois pas ce qui peut clocher. D'ailleurs, un copier-coller dans un fichier de code ne remonte pas d'erreur de ce genre à la compilation. Tout ce que je peut anticiper ce sont des warning par rapport à des références non déclarées nullables qui ne sont pas instanciées à la création de l'objet conteneur, mais c'est encore autre chose. Est-ce-qu'il manque du contexte ? Les deux idées qui me viennent sont :
    - une collision de nom de type par rapport aux namespaces utilisés, avec deux type nomType ;
    - la déclaration d'un opérateur de cast explicite qui empêcherait d'avoir un opérateur de cast implicite.
    Mais ce sont vraiment des "edge cases", ça me paraît quand même assez improbable.

  7. #7
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 197
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Noxen Voir le message
    Par rapport au code proposé je ne vois pas ce qui peut clocher. D'ailleurs, un copier-coller dans un fichier de code ne remonte pas d'erreur de ce genre à la compilation. Tout ce que je peut anticiper ce sont des warning par rapport à des références non déclarées nullables qui ne sont pas instanciées à la création de l'objet conteneur, mais c'est encore autre chose. Est-ce-qu'il manque du contexte ? Les deux idées qui me viennent sont :
    - une collision de nom de type par rapport aux namespaces utilisés, avec deux type nomType ;
    - la déclaration d'un opérateur de cast explicite qui empêcherait d'avoir un opérateur de cast implicite.
    Mais ce sont vraiment des "edge cases", ça me paraît quand même assez improbable.
    Souci avec la version de C# ?

    Pour info c'est un projet .NET Framework 4.7.1

    Pour le collision, c'est pas impossible.
    Il s'agit de code décompilé, dispersé à l'origine dans plusieurs DLLs.
    J'ai peut-être merdé en récupérant le code. D'ailleurs j'ai été obligé de repartir à zéro car j'avais à un moment mélangé deux namespaces différents.

    Ceci dit, le souci se corrigeait sans problème en mettant un cast explicite, ce qui aurait dû planter de la même manière si c'était un souci de mélange de types dans des namespaces différents.

  8. #8
    Membre Expert
    Homme Profil pro
    edi
    Inscrit en
    Juin 2007
    Messages
    941
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : edi

    Informations forums :
    Inscription : Juin 2007
    Messages : 941
    Par défaut
    Citation Envoyé par fred1599 Voir le message
    Ok, je te fais confiance pour le C#

    Mais new à mon sens n'assure pas le type réel de l'objet à la compilation, ou je me trompe ?

    Par contre je vois cela dans la documentation,



    Du coup je pense qu'il faut prendre en compte la valeur null car il semble que cet opérateur n'échoue jamais...
    Il n'y a pas de souci avec l'opérateur new seul, il s'agit d'une simple élision de code lorsque le contexte est suffisant pour permettre au compilateur de déterminer le type approprié (inférence de type).

    Déclaration classique :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Point p = new Point(1, 2);
    Avec le mot-clé var le type est déduit de la source de l'affectation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    var p = new Point(1, 2);
    Si le type de la variable est déclaré explicitement, il n'est pas nécessaire de le répéter avec l'opérateur new :
    Bien sûr le compilateur va râler s'il n'a pas suffisamment d'informations :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    var p = default;
    var p = null;
    var p = new(1, 2);
    On peut toujours utiliser des types explicites lorsque le type de la variable n'est pas le même que celui de l'objet :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    IFormatable p = new Point(1, 2); // System.Windows.Point implémente System.IFormatable

Discussions similaires

  1. un menu géré avec javascript sur plusieurs niveaux (logique)
    Par polothentik dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 02/07/2008, 14h23
  2. [ZF 1.5] Suppression en cascade sur plusieurs niveaux
    Par Janitrix dans le forum Zend_Db
    Réponses: 12
    Dernier message: 12/05/2008, 02h38
  3. [SQL] Affichage sur plusieurs niveaux
    Par oim dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 10/12/2007, 14h52
  4. [Hibernate] Héritage sur plusieurs niveaux
    Par srvremi dans le forum Hibernate
    Réponses: 2
    Dernier message: 31/05/2006, 18h39

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