157 votes

Comment appeler de la base.de la base.méthode()?

// Cannot change source code
class Base
{
    public virtual void Say()
    {
        Console.WriteLine("Called from Base.");
    }
}

// Cannot change source code
class Derived : Base
{
    public override void Say()
    {
        Console.WriteLine("Called from Derived.");
        base.Say();
    }
}

class SpecialDerived : Derived
{
    public override void Say()
    {
        Console.WriteLine("Called from Special Derived.");
        base.Say();
    }
}

class Program
{
    static void Main(string[] args)
    {
        SpecialDerived sd = new SpecialDerived();
        sd.Say();
    }
}

Le résultat est:

Called from Special Derived.
Called from Derived. /* this is not expected */
Called from Base.

Comment puis-je réécrire SpecialDerived classe de sorte que la classe moyenne "est Dérivé de"s'méthode n'est pas appelée?

Mise à JOUR: La raison pourquoi je veux hériter de la Dérivée au lieu de la Base est Dérivé de la classe contient beaucoup d'autres implémentations. Puisque je ne peux pas faire base.base.method() ici, je suppose que la meilleure façon est de faire les choses suivantes?

// Ne peut pas modifier le code source

class Derived : Base
{
    public override void Say()
    {
        CustomSay();

        base.Say();
    }

    protected virtual void CustomSay()
    {
        Console.WriteLine("Called from Derived.");
    }
}

class SpecialDerived : Derived
{
    /*
    public override void Say()
    {
        Console.WriteLine("Called from Special Derived.");
        base.Say();
    }
    */

    protected override void CustomSay()
    {
        Console.WriteLine("Called from Special Derived.");
    }
}

103voto

Eric Lippert Points 300275

C'est une mauvaise programmation de la pratique, et ne sont pas autorisées en C#. C'est une mauvaise pratique car

  • Les détails de la grandbase sont des détails de mise en œuvre de la base; vous ne devriez pas compter sur eux. La classe de base est de fournir une abstraction overtop de la grandbase; vous devriez être en utilisant cette abstraction, non de la construction d'une voie de contournement pour l'éviter.

  • Dérivée à partir de votre base parce que vous aimez ce qu'il fait et souhaitez réutiliser et de les étendre. Si vous n'aimez pas ce qu'il fait et qui veulent travailler autour d'elle plutôt que de travailler avec elle, alors pourquoi vous en découlent en premier lieu? Tirer de la grandbase vous-même si c'est la fonctionnalité que vous souhaitez utiliser et à étendre.

  • La base peut nécessiter certains invariants de la sécurité ou de la sémantique des raisons de cohérence qui sont maintenus par les détails de la façon dont la base utilise les méthodes de la grandbase. Permettant une classe dérivée de la base d'ignorer le code qui maintient ces invariants pourrait mettre la base en est incohérent, l'état corrompu.

24voto

rh. Points 878

Vous ne pouvez pas partir de C#. De IL, c'est en fait pris en charge. Vous pouvez faire un non-virt appel à l'un de vos parents des classes... mais s'il vous plaît ne le font pas. :)

10voto

JoshJordan Points 8869

La réponse (qui je sais n'est pas ce que vous cherchez) est:

class SpecialDerived : Base
{
    public override void Say()
    {
        Console.WriteLine("Called from Special Derived.");
        base.Say();
    }
}

La vérité est, vous n'avez qu'une interaction directe avec la classe que vous hérite. Penser de cette classe comme une couche de fournir autant ou aussi peu de celui-ci ou l'un de ses parents fonctionnalités qu'il désire pour ses classes dérivées.

EDIT:

Votre montage fonctionne, mais je pense que je voudrais utiliser quelque chose comme ceci:

class Derived : Base
{
    protected bool _useBaseSay = false;

    public override void Say()
    {
        if(this._useBaseSay)
            base.Say();
        else
            Console.WriteLine("Called from Derived");
    }
}

Bien sûr, dans une mise en œuvre réelle, vous pourriez faire quelque chose de plus comme cela pour l'extensibilité et la facilité de maintenance:

class Derived : Base
{
    protected enum Mode
    {
        Standard,
        BaseFunctionality,
        Verbose
        //etc
    }

    protected Mode Mode
    {
        get; set;
    }

    public override void Say()
    {
        if(this.Mode == Mode.BaseFunctionality)
            base.Say();
        else
            Console.WriteLine("Called from Derived");
    }
}

Ensuite, les classes dérivées peuvent contrôler leurs parents de l'état de façon appropriée.

5voto

Rajesh Points 11

Vous pouvez également faire une simple fonction de premier niveau de la classe dérivée, à l'appel du grand de la fonction de base

1voto

yo hal Points 1949

Dans le cas où vous n'avez pas accès à la classe dérivée de la source, mais besoin de tous les source de la classe dérivée en plus de la méthode actuelle, alors j'aurais recommandé que vous devriez également faire une classe dérivée et l'appel à la mise en œuvre de la classe dérivée.

Voici un exemple:

//No access to the source of the following classes
public class Base
{
     public virtual void method1(){ Console.WriteLine("In Base");}
}
public class Derived : Base
{
     public override void method1(){ Console.WriteLine("In Derived");}
     public void method2(){ Console.WriteLine("Some important method in Derived");}
}

//Here should go your classes
//First do your own derived class
public class MyDerived : Base
{         
}

//Then derive from the derived class 
//and call the bass class implementation via your derived class
public class specialDerived : Derived
{
     public override void method1()
     { 
          MyDerived md = new MyDerived();
          //This is actually the base.base class implementation
          MyDerived.method1();  
     }         
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X