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 :

Différence précise entre virtual / override et new


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Décembre 2007
    Messages
    54
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2007
    Messages : 54
    Par défaut Différence précise entre virtual / override et new
    Bonjour à tous,

    J'essaye depuis quelques heures de comprendre le différence *exacte* les mots clefs virtual (qui semble aller de pair avec override) et new.

    Je prends un exemple de msdn : http://msdn.microsoft.com/fr-fr/libr...=vs.80%29.aspx
    Ils illustrent ici l'utilisation du mot cle override. Je pense l'avoir bien compris, rien de bien complexe.

    Seulement, lorsque j'apporte les modifs suivantes :
    - J'enlève le mot clef virtual de la méthode CalculatePay() dans la classe Employee
    - Je remplace public override decimal CalculatePay() par public new decimal CalculatePay() dans la classe SalesEmployee (qui hérite d'Employee)

    ...

    Le résultat est strictement identique...

    Après avoir arpenté pas mal de sites web, j'ai vu que l'utilisation de new était déconseillée... Mais j'ai pas vraiment compris pourquoi.

    Quelqu'un aurait-il une explication ou un exemple afin que je comprenne clairement ?

    D'avance merci

  2. #2
    Membre chevronné Avatar de Jerede
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mai 2010
    Messages
    271
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mai 2010
    Messages : 271
    Par défaut
    Bonsoir,

    Ce n'est pas du tout pareil !
    Un exemple pour illustrer la chose :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class Entity
        {
            public virtual void Execute()
            {
                Console.WriteLine("salut, je suis dans entity");
            }
     
            public void Execute2()
            {
                Console.WriteLine("salut, je suis dans entity");
            }
        }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class Human : Entity
        {
            public override void Execute()
            {
                Console.WriteLine("salut, je suis dans Human");
            }
     
            public new void Execute2()
            {
                Console.WriteLine("salut, je suis dans Human");
            }
        }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Program
        {
            static void Main(string[] args)
            {
                Entity human = new Human();
     
                human.Execute(); // => Je suis dans Human
     
                human.Execute2(); // => Je suis dans Entity
     
                Console.Read();
            }      
        }
    Ici on caste notre "Human" en Entity.
    Dans le cas n°1, celui de l'override, la classe Human à écrasé la méthode de la classe Entity, comme tu peut le voir, c'est donc la méthode de Human qui est appelé.
    Dans le cas n°2 avec new, la méthode de la classe Entity n'a pas était écrasé, c'est donc celle-ci qui est appelé. "new" ne fait que cacher la méthode de Entity dans la classe Human.

  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 : 43
    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
    Par défaut
    Pour compléter l'explication de Jerede :

    La différence est en fait liée au polymorphisme. Quand tu overrides dans une classe Derived une méthode virtual M définie dans une classe Base, tu redéfinis son implémentation : ça reste la même méthode, mais c'est l'implémentation spécifique de la classe courante qui sera appelée. Si tu as une variable x de type Base qui fait référence à une instance de la classe Derived, x.M() fera appel à Derived.M() et non à Base.M().

    Quand tu fais un new sur une méthode, tu caches l'implémentation de la classe de base. Ca introduit une nouvelle méthode, qui n'a pas de lien avec la méthode de même nom de la classe de base. Cette méthode ne participe pas au polymorphisme, et sera appelée seulement via une variable de la classe dérivée. Pour reprendre l'exemple précédent, x.M() appelera Base.M(), pas Derived.M() (toujours en supposant que x est déclarée de type Base)

    Je reprends l'exemple de Jerede en le complétant un peu :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
                Human human = new Human();
                Entity entity = human;
     
                entity.Execute(); // => Je suis dans Human 
                human.Execute();  // => Je suis dans Human 
     
                entity.Execute2(); // => Je suis dans Entity
                human.Execute2(); // => Je suis dans Human
    On voit bien que dans le cas de la méthode virtuelle, c'est toujours l'implémentation de Human qui est appelée, même à partir d'une variable de type Entity.

    En revanche, les appels à Execute2 (non virtuelle) appellent en fait 2 méthodes différentes, selon le type de la variable, bien que les 2 variables fassent référence au même objet



    Si l'utilisation de new est déconseillée, c'est parce que si tu manipules l'objet via une variable de la classe de base, ta méthode redéfinie avec new ne sera pas appelée. Par exemple, dans un contrôle WinForms, si tu redéfinis OnPaint en faisant new au lieu de override, ta méthode ne sera pas appelée car l'appel est fait via une variable de type Control, et non le type de ton contrôle

  4. #4
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
                Human human = new Human();
                Entity entity = human;
     
                entity.Execute(); // => Je suis dans Human 
                human.Execute();  // => Je suis dans Human 
     
                entity.Execute2(); // => Je suis dans Entity
                human.Execute2(); // => Je suis dans Human
    Petite coquille non?

  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 : 43
    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
    Par défaut
    Citation Envoyé par Nathanael Marchand Voir le message
    Petite coquille non?
    Oups
    Merci, c'est corrigé

  6. #6
    Membre averti
    Profil pro
    Étudiant
    Inscrit en
    Décembre 2007
    Messages
    54
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2007
    Messages : 54
    Par défaut
    Merci pour ces réponses illustrées, je crois que je commence à saisir le principe

    En revanche, je vois pas dans quel(s) cas on a intérêt à écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Entity human = new Human();
    Je veux dire par là que je si veux créer une nouvelle instance de Human, j'aurai tendance à écrire tout simplement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Human human = new Human();

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

Discussions similaires

  1. Différence entre virtual et abstract
    Par _LVEB_ dans le forum C#
    Réponses: 8
    Dernier message: 29/09/2015, 17h21
  2. Difference entre New et (virtual / override)
    Par shimomura22 dans le forum C#
    Réponses: 2
    Dernier message: 16/04/2015, 21h08
  3. difference entre virtual-override-Dynamic ?
    Par Jcpan dans le forum Débuter
    Réponses: 7
    Dernier message: 07/04/2010, 12h52
  4. Différence entre MaClasse m; et new MaClasse?
    Par Jean_Benoit dans le forum C++
    Réponses: 2
    Dernier message: 12/10/2006, 21h03
  5. [C#] Différences entre Virtual et Abstract
    Par kunfuka dans le forum C#
    Réponses: 2
    Dernier message: 11/11/2005, 12h14

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