web-dev-qa-db-ger.com

Warum kann ich keinen abstrakten Konstruktor für eine abstrakte C # -Klasse erstellen?

Ich erstelle eine abstrakte Klasse. Ich möchte, dass jede meiner abgeleiteten Klassen gezwungen wird, eine bestimmte Signatur des Konstruktors zu implementieren. Als solches habe ich getan, was ich getan hätte, wollte ich sie zwingen, eine Methode zu implementieren, machte ich eine abstrakte.

public abstract class A
{
    abstract A(int a, int b);
}

Ich erhalte jedoch die Meldung, dass der abstrakte Modifikator für diesen Artikel ungültig ist. Mein Ziel war es, Code wie diesen zu erzwingen.

public class B : A
{
    public B(int a, int b) : base(a, b)
    {
        //Some other awesome code.
    }
}

Dies ist der gesamte C # .NET-Code. Kann mir jemand weiterhelfen?

pdate 1

Ich wollte einige Dinge hinzufügen. Was ich am Ende hatte, war das hier.

private A() { }

protected A(int a, int b)
{
    //Code
}

Das macht, was einige Leute sagen, Standard ist privat, und die Klasse muss einen Konstruktor implementieren. Dies erzwingt jedoch keinen Konstruktor mit der Signatur A (int a, int b).

public abstract class A
{
    protected abstract A(int a, int b)
    {


    }
}

pdate 2

Um dies zu umgehen, habe ich meinen Standardkonstruktor privat und meinen anderen Konstruktor geschützt. Ich bin nicht wirklich auf der Suche nach einer Möglichkeit, meinen Code zum Laufen zu bringen. Ich habe mich darum gekümmert. Ich möchte verstehen, warum C # dies nicht zulässt.

58
Anthony D

Sie können keinen abstrakten Konstruktor haben, da abstrakt bedeutet, dass Sie ihn in einer nicht abstrakten untergeordneten Klasse überschreiben müssen und einen Konstruktor nicht überschreiben können.

Wenn Sie darüber nachdenken, ist dies sinnvoll, da Sie immer den Konstruktor der untergeordneten Klasse (mit dem neuen Operator) aufrufen und niemals die Basisklasse.

Im Allgemeinen besteht die einzige Möglichkeit in C #, eine bestimmte Konstruktorsignatur zu erzwingen, in der Verwendung der generischen Einschränkung new (), mit der die Existenz eines parameterlosen Konstruktors für den Typparameter erzwungen wird.

51
Tamas Czinege

Ändern Sie diesen Konstruktor in Klasse A in

protected A(int a, int b)
{
    // Some initialisation code here
}

Dann müssen Ihre Unterklassen es verwenden, da es keinen Standardkonstruktor gibt.

Sie können jedoch immer noch die tatsächliche Signatur des Konstruktors ändern. Es gibt meines Wissens keine Möglichkeit, eine Unterklasse zu zwingen, eine bestimmte Signatur für ihren Konstruktor zu verwenden. Ich bin mir ziemlich sicher, dass Konstruktoren nicht abstrakt sein können.

Wofür genau brauchst du das? Möglicherweise können wir eine Lösung vorschlagen.

26
Jamie Penney

Obwohl Sie Konstruktoren nicht überschreiben können und daher keinen abstrakten Konstruktor definieren können, können Sie eine abstrakte Factory-Methode in Ihre abstrakte Basisklasse einfügen. Alle abgeleiteten Klassen müssten dies überschreiben.

public abstract class A 
{ 
    abstract A MakeAInstance(int a, int b); 
} 

public class B : A 
{ 
    // Must implement:
    override A MakeAInstance(int a, int b) {
        // Awesome way to create a B instance goes here
    }
} 
7
John Saunders

Mehrere Gründe:

1) Konstruktoren werden nicht vererbt, daher können Sie sie nicht überschreiben.

2) Der Konstruktor ist eine statische Elementfunktion, da keine bestimmte Instanz aufgerufen werden muss. Abstrakt bedeutet "virtuell", was bedeutet, dass die Implementierung je nach Unterklassen einer bestimmten Instanz variieren kann. Dies ist das Gegenteil der Absicht der Bedeutung des Schlüsselworts "static".

5
Mats

Sie können keine Konstruktorsignatur erzwingen, da jede abgeleitete Klasse ihre eigenen Konstruktoren definieren kann (muss!) Und beliebige Parameter annehmen kann.

Wenn Sie eine bestimmte Menge von Variablen an ein Objekt einer abgeleiteten Klasse übergeben müssen, definieren Sie eine abstrakte Methode, die von abgeleiteten Klassen implementiert werden muss. Wenn die Klassen die abstrakte Methode nicht implementieren, wird ein Compilerfehler ausgegeben.

4
devio

ich hoffe, dies wird jemandem helfen, wie ich bin. Ich habe versucht, eine "normale" öffentliche Klasse mit einem ctor zu erstellen, der Argumente akzeptiert, und dann musste ich daraus eine untergeordnete Klasse machen, sodass ich einen leeren ctor dafür brauchte.

ich wusste das vorher nicht: Wenn Sie ein geschütztes ctor machen, dann sieht die Kinderklasse es, aber der Rest des Programms sieht es nicht (ich denke, meine Verwirrung ist, da ich in asp.net alle geschützten in der aspx-Seite sehe, die von erbt die cs ...)

1
bresleveloper

Alle Unterklassen können immer ihren eigenen Konstruktor angeben, solange sie einen Konstruktor der Superklasse aufrufen. Es gibt also keine Möglichkeit, eine Klasse zu einem bestimmten Konstruktor zu zwingen (zumindest funktioniert dies in Java so). Wenn Sie ein Factory-Muster verwenden, erhalten Sie möglicherweise einen Vorteil - Sie können eine Factory-Methode in einer Schnittstelle definieren -, aber Sie benötigen eine separate Factory-Klasse, da Ihre abstrakte Basisklasse die tatsächliche Klasse des Objekts, das sein muss, nicht kennt erstellt.

Allerdings: Wenn Sie ein konkreteres Beispiel für das Problem hinzufügen, werden Sie möglicherweise zu anderen/besseren Antworten aufgefordert. Suchen Sie nach generischem Instantiierungscode oder müssen bestimmte Einstellungen für die abstrakte Basisklasse vorgenommen werden?

Wenn Sie sich nur Gedanken über die Initialisierung machen, die von der abstrakten Klasse durchgeführt werden muss, erstellen Sie eine Methode, um dies zu tun, und dokumentieren Sie die Verwendung dieser Methode.

0

ich bin mir nicht sicher, ob dies hilft - aber ich denke, dies wäre eine Lösung für Ihr Problem:

public class A
{
  public A(int a, int b)
  {
    DoSomething(int a, int b);
  }

  virtual public void DoSomething(int a, int b)
  {

  }
}

public class B : A
{
  override public void DoSomething(int a, int b)
  {
    //class specific stuff
  }
}

mit dem Ergebnis, dass Sie einen Konstruktor mit den erforderlichen Argumenten in einer abgeleiteten Klasse mit dem richtigen Verhalten aufrufen können.

0
mo.