为什么可以';我不能在抽象C#类上创建一个抽象构造函数吗?

为什么可以';我不能在抽象C#类上创建一个抽象构造函数吗?,c#,inheritance,oop,constructor,abstract-class,C#,Inheritance,Oop,Constructor,Abstract Class,我正在创建一个抽象类。我希望强制每个派生类实现构造函数的特定签名。因此,如果我想强迫他们实现一个方法,我就做了我应该做的,我做了一个抽象的方法 public abstract class A { abstract A(int a, int b); } 但是,我收到一条消息,说抽象修饰符在此项上无效。我的目标是强制执行这样的代码 public class B : A { public B(int a, int b) : base(a, b) { //Som

我正在创建一个抽象类。我希望强制每个派生类实现构造函数的特定签名。因此,如果我想强迫他们实现一个方法,我就做了我应该做的,我做了一个抽象的方法

public abstract class A
{
    abstract A(int a, int b);
}
但是,我收到一条消息,说抽象修饰符在此项上无效。我的目标是强制执行这样的代码

public class B : A
{
    public B(int a, int b) : base(a, b)
    {
        //Some other awesome code.
    }
}
这都是C#.NET代码。有人能帮我吗

更新1

我想补充一些东西。我的结局是这样的

private A() { }

protected A(int a, int b)
{
    //Code
}
这就是一些人所说的,默认值是私有的,类需要实现一个构造函数。然而,这并不强制使用签名为a(inta,intb)的构造函数

更新2


我应该很清楚,为了解决这个问题,我将我的默认构造函数设置为私有,而另一个构造函数则受保护。我并不是真的在寻找让我的代码工作的方法。我处理好了。我想了解为什么C不允许你这么做。

将类A中的构造函数更改为

protected A(int a, int b)
{
    // Some initialisation code here
}
然后您的子类将不得不使用它,因为没有默认构造函数

但是,它们仍然可以更改构造函数的实际签名。据我所知,没有办法强迫子类为其构造函数使用特定的签名。我很确定构造函数不能是抽象的


你到底需要这个做什么?我们可能会建议解决这个问题。

您不能强制构造函数签名,因为每个派生类可能(必须!)定义自己的构造函数,并且它们可以使用自己喜欢的任何参数


如果需要将给定的变量集传递给派生类的对象,请定义需要由派生类实现的抽象方法。如果类没有实现抽象方法,您将得到一个编译器错误。

所有子类都可以指定自己的构造函数,只要它们调用超类的构造函数-因此无法强制类具有特定的构造函数(至少在Java中是这样)。您可以看到,使用工厂模式将使您有所收获—您可以在接口中定义工厂方法—但您需要一个单独的工厂类,因为您的抽象基类不知道需要创建的对象的实际类

然而:也许添加一个更具体的例子来说明你所遇到的问题可能会引发其他/更好的反应。您是在寻找一些通用的实例化代码,还是担心必须对抽象基类进行特定的设置


如果您只关心必须由抽象类完成的初始化,请创建一个方法来完成初始化,并记录该方法的使用。

您不能拥有抽象构造函数,因为抽象意味着您必须在任何非抽象子类中重写它,并且不能重写构造函数

如果您仔细想想,这是有意义的,因为您总是调用子类的构造函数(使用新运算符),而从不调用基类


一般来说,在C#中,强制执行特定构造函数签名的唯一方法是使用new()泛型约束,该约束强制存在类型参数的无参数构造函数。

不确定这是否有帮助-但我觉得这将是您问题的解决方案:

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
  }
}

这样,您就可以在任何具有正确行为的派生类中使用所需参数调用构造函数

尽管不能重写构造函数,因此不能定义抽象构造函数,但可以在抽象基类中放置抽象工厂方法。所有的派生类都需要覆盖它

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
    }
} 
多重原因:

1) 构造函数不是继承的,因此不能重写它们


2) 构造函数是一个静态成员函数,因为它不需要调用特定的实例。抽象意味着“虚拟”,这意味着实现可以根据特定实例的子类化方式而有所不同,这与“静态”关键字的含义相反。

希望这能帮助像我这样的新手 我想创建一个带有接受参数的ctor的“普通”公共类,然后我需要将其设置为子类,所以我需要一个空ctor


我以前不知道这一点:如果你做了一个受保护的ctor,那么子类会看到它,但程序的其余部分却看不到它(我想我的困惑是,在asp.net中,我在aspx页面中看到了从cs继承的所有受保护的ctor…

我认为他们可以添加其他构造函数(使用不同的签名),但他们将被迫实现至少在受保护的“构造函数”中定义的签名。这个答案并不能实现我想要的。C#6是否会用主构造函数更改此规则?这是一个输入错误,(应该是int b)但我的答案与Jamie非常相似,这就是我删除我的答案的原因。今天,POO worlds不理解覆盖共享的概念(构造函数是共享方法,如果.net表示它不是共享的,那么它实际上是一个共享方法,因为你可以在任何地方调用它,它不需要实例)。因此覆盖共享是一个很少有语言(如Haskell)理解的奇怪特性。但是在这种情况下,您必须首先创建类B的实例,以便能够调用方法MakeAInstance并获得新的实例是的,确切地说,或者必须将一个实例传递给您的代码,然后调用
实例.MakeAInstance(1,2)
不建议在构造函数中调用重写。我不同意您关于构造函数是静态成员的说法,它确实需要调用实例(因为您可以访问实例方法、字段等)。关键字实例化对象,然后调用构造函数,构造函数本身不“构造”对象
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
    }
}