Frage

Wie erklären Sie eine Methode in C #, die (oder außer Kraft gesetzt werden) durch eine dereived Klasse außer Kraft gesetzt werden sollten - möglicherweise sogar vor der Montage - aber das sollte nur innerhalb der tatsächlichen Klasse aufrufbar sein

(d. Wie eine private virtuelle Funktion in C ++)

[Bearbeiten]
private virtual ist genau das, was ich beabsichtige: „Hier ist ein Weg, um mein Verhalten zu ändern, aber Sie sind noch nicht über diese Funktion direkt aufrufen darf (weil es ruft arkanen Anrufungen erfordert, dass meine Basisklasse nur tun soll) „

So ist es zu klären: Was ist der beste Ausdruck für die in C #

War es hilfreich?

Lösung

C # macht eine stärkere Garantie für "private" als C ++ tut. In C ++ können Sie in der Tat eine private virtuelle Methode außer Kraft setzen. Aber das bedeutet, dass Code in einer Basisklasse Code in einer abgeleiteten Klasse ausführen kann. Bricht das Versprechen, dass die private Methode wirklich privat ist und nur durch Methoden in der gleichen Klasse aufgerufen werden.

Etwas, das hier nicht helfen, ist, dass C ++ erfordert nicht das Schlüsselwort virtual wiederholen. Was zu hart bis Reverse-Engineering Geheimnisse wie diese:

#include "stdafx.h"
#include <iostream>

class Base {
private:
    virtual void Method() = 0;
public:
    void Test() {
        Method();
    }
};
class Derived : public Base {
private:
    void Method() { std::cout << "Who the heck called me?"; }
};

int _tmain(int argc, _TCHAR* argv[])
{
    Base* p = new Derived;
    p->Test();
}

Ich bin damit einverstanden, es gibt eine mögliche Rolle für private Erbschaft. Die Sprache C # Designer sagte Nein! though.

Andere Tipps

Wenn Sie sagen, es ist nur aufrufbar „innerhalb der eigentlichen Klasse“ sein sollte, meinen Sie die Basisklasse oder die abgeleitete Klasse? Keines von beiden ist möglich für sich allein. Die nächste ist eine geschützte Methode zu verwenden, was bedeutet, dass es aus der Erklärung der Klasse aufgerufen werden, die abgeleiteten Klasse, und jede weiteren abgeleitete Klasse.

Ein privates Mitglied ist Kind-Klassen nicht sichtbar. Ich denke, geschützten virtuellen wird die Art und Weise durchführen Sie möchten?

UPDATE:

Hier im Detail ist ein explaination von dem, was Sie mit Vererbung und übergeordneten Funktionen innerhalb von C # tun können. Ich versuchte, ein wenig aussagekräftig Beispiel zu verwenden, aber halte es für selbstverständlich, dass sein ein schlechtes Klassendesign und ich würde immer nicht empfehlen, die Klassen auf diese Weise beschrieben zu implementieren. Ich hoffe jedoch, vielleicht geben diese Ihnen eine Allee Ihre ursprüngliche Problem in einer Weise zu nähern Lösung, die akzeptabel sein könnte. Es gibt keine Möglichkeit, eine konkrete Klasse zu verhindern, dass eines ihrer Mitglieder fordern, aber wenn Sie Ihre Struktur wie dies in irgendeiner Weise, vielleicht seine nicht erteilen.

public abstract class Animal
{
    public void DisplayAttributes()
    {
        Console.WriteLine(Header());
        Console.WriteLine("Name: " + Name());
        Console.WriteLine("Legs: " + Legs());
        Console.WriteLine();
    }

    protected virtual int Legs()
    {
        return 4;
    }

    private string Header()
    {
        return "Displaying Animal Attributes";
    }

    protected abstract string Name();
}

public class Bird : Animal
{
    protected override string Name()
    {
        return "Bird";
    }

    protected override int Legs()
    {
        return 2;
    }
}

public class Zebra : Animal
{
    protected override string Name()
    {
        return "Zebra";
    }
}

public class Fish : Animal
{
    protected override string Name()
    {
        return "Fish";
    }

    protected override int Legs()
    {
        return 0;
    }

    private string Header()
    {
        return "Displaying Fish Attributes";
    }

    protected virtual int Gils()
    {
        return 2;
    }

    public new void DisplayAttributes()
    {
        Console.WriteLine(Header());
        Console.WriteLine("Name: " + Name());
        Console.WriteLine("Gils: " + Gils());
        Console.WriteLine();
    }
}

class Program
{
    static void Main(string[] args)
    {
        Bird bird = new Bird();
        bird.DisplayAttributes();
        //Displaying Animal Attributes
        //Name: Bird
        //Legs: 2

        Zebra zebra = new Zebra();
        zebra.DisplayAttributes();
        //Displaying Animal Attributes
        //Name: Zebra
        //Legs: 4


        Fish fish = new Fish();
        fish.DisplayAttributes();
        //Displaying Fish Attributes
        //Name: Fish
        //Gils: 2

        List<Animal> animalCollection = new List<Animal>();
        animalCollection.Add(bird);
        animalCollection.Add(zebra);
        animalCollection.Add(fish);

        foreach (Animal animal in animalCollection)
        {
            animal.DisplayAttributes();
            //Displaying Animal Attributes
            //Name: Bird
            //Legs: 2

            //Displaying Animal Attributes
            //Name: Zebra
            //Legs: 4

            //Displaying Animal Attributes
            //Name: Fish
            //Legs: 0
            //*Note the difference here
            //Inheritted member cannot override the
            //base class functionality of a non-virtual member
        }
    }
}

In diesem Beispiel, Vogel, Zebra, und Fische könnten alle ihre Namen und Beine Methoden nennen, aber im Rahmen, wenn dieses Beispiel würde es nicht unbedingt Nutzen dabei sein. wie von Fisch zusätzlich gezeigt, kann der DisplayAttributes () für eine Instanz von einer konkreten abgeleiteten Klasse modifiziert werden; aber wenn man in einem Tier suchen, wie in der foreach-Schleife, erhalten Sie die Basisklassen DisplayAttributes Verhalten, unabhängig von der tatsächlichen Art des Tieres. Ich hoffe, dies kann helfen, die Art von Funktionalität povide Sie replizieren möchten.

Haben Sie betrachten die Verwendung eines Delegierten, das zu tun? Sie können die abgeleitete Klasse ermöglichen, die Delegierten über einige geschützte Eigenschaft festlegen oder es zu einem Konstruktor übergeben. Sie können auch die Vertreter der internen Implementierung Standard, die eine private Methode auf Ihrer Basisklasse ist.

Hier ist ein Beispiel dafür, was vboctor bereits erwähnt:

public class Base
{
    private Func<Base, int> func;
    protected void SetFunc(Func<Base, int> func)
    {
        this.func = func;
    }

    private void CallFunc()
    {
        if (func != null)
        {
            var i = func(this);
        }
    }
}

public class Sub : Base
{
    private void DoFuncyStuff()
    {
         this.SetFunc(b => 42);
    }
}

Warum brauchen Sie es privat sein? Geschützte sollte ausreichend sein, hier. Sie fragen die Unterklasse Autor, Code zu schreiben, dass sie nicht aufrufen können. Was bedeutet das erreichen? Sie können trotzdem diesen Code verwenden.

Wie ich Ihre Frage gelesen, Sie zwei Dinge bedeuten könnte.

Erstens, wenn, wenn Sie eine Funktion in der Klasse A wollen, die in der Kinderklasse B außer Kraft gesetzt werden können, ist aber zu jedem außerhalb der Klasse nicht sichtbar:

public class ClassA
{
  protected virtual ReturnType FunctionName(...) { ... }
}

public class ClassB
{
  protected override ReturnType FunctionName(...) { ... }
}

Zweitens, wenn Sie eine implementierende Klasse zwingen, um die Funktion zu definieren:

public abstract class ClassA
{
  protected abstract ReturnType FunctionName(...);
}

public class ClassB
{
  protected override ReturnType FunctionName(...) { ... }
}

Ein weiteres Konzept man sich anschaut, könnte, wenn man nur Graben in C #, die irgendwie verwandt sind Teilklassen. Das ist die Idee von zwei Quelldateien während der Kompilierung kombiniert werden, eine Klasse zu erstellen, die beide aus der gleichen Assembly:

Datei 1:

public partial class ClassA
{
    private ReturnType FunctionName(...);
}  

Datei 2:

public partial class ClassA
{
  //actual implimentation
  private ReturnType FunctionName(...){ ... }; 
}

Partials sind nicht weit verbreitet, außer wenn sie mit entworfen generierten Dateien, wie die Linq2Sql Dateien oder EDM, oder WinForms zu tun, etc.

denke, das wird nicht funktionieren, wie Sie gedacht, aber lassen Sie mich für Sie einige Pseudo-Code skizzieren:

public interface BaseClassFunction {
    void PleaseCallMe();
}

public class BaseClass {
    private BaseClassFunction fn;
    public BaseClass(BaseClassFunction fn) {
        this.fn = fn;
    }
    private CallMe() {
        fn.PleaseCallMe();
    }
    public PublicCallMe() {
        CallMe();
    }
}

private class DerivedClassFunction : BaseClassFunction {
    void PleaseCallMe() { ... do something important ... }
}

public class DerivedClassFunction {
    public DerivedClassFunction() : BaseClass(new DerivedClassFunction()) {
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top