为什么我不能在抽象C#类上创建抽象构造函数?

时间:2009-02-02 21:21:00

标签: 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)
    {
        //Some other awesome code.
    }
}

这是所有C#.NET代码。任何人都可以帮助我吗?

更新1

我想添加一些东西。我最终得到的是这个。

private A() { }

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

这就是一些人所说的,默认是私有的,并且类需要实现构造函数。但是,这不会强制带有签名A(int a,int b)的构造函数。

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


    }
}

更新2

我应该清楚,为了解决这个问题,我将默认构造函数设为私有,并保护我的其他构造函数。我并不是在寻找一种让我的代码工作的方法。我照顾好了。我希望了解为什么C#不允许你这样做。

8 个答案:

答案 0 :(得分:50)

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

如果你考虑一下,这是有道理的,因为你总是调用子类的构造函数(使用new运算符)而不是基类。

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

答案 1 :(得分:26)

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

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

然后你的子类必须使用它,因为没有默认的构造函数。

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

你到底需要什么?我们或许可以建议解决这个问题。

答案 2 :(得分:6)

虽然您无法覆盖构造函数,因此无法定义抽象构造函数,但您可以在抽象基类中放置抽象工厂方法。所有派生类都需要覆盖它。

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

答案 3 :(得分:5)

多种原因:

1)构造函数不会被继承,因此您无法覆盖它们。

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

答案 4 :(得分:4)

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

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

答案 5 :(得分:1)

希望这会像我一样帮助一个人 我正在寻找一个“正常”的公共课,其中一个ctor接受争论,然后我需要把它变成一个儿童课,所以我需要一个空的ctor。

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

答案 6 :(得分:0)

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

但是:可能会添加一个更具体的问题示例,可能会提示其他/更好的回复。您是否在寻找一些通用的实例化代码,或者您是否担心必须在抽象基类上进行特定设置?

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

答案 7 :(得分:0)

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

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

结果是您可以使用正确的行为在任何派生类中调用具有所需参数的构造函数。