64

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

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# 不允许您这样做。

4

8 回答 8

54

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

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

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

于 2009-02-03T18:46:10.570 回答
25

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

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

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

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

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

于 2009-02-02T21:24:48.910 回答
7

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

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
    }
} 
于 2010-05-05T19:55:07.893 回答
5

多种原因:

1)构造函数不是继承的,因此您不能覆盖它们。

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

于 2012-03-29T05:50:04.003 回答
4

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

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

于 2009-02-02T21:28:58.480 回答
1

希望这对新手有所帮助,因为我正在寻找一个带有接受参数的 ctor 的“普通”公共课程,然后我需要将其设为子课程,因此我需要一个空的 ctor。

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

于 2012-07-10T10:04:37.367 回答
0

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

但是:也许添加您遇到的问题的更具体示例可能会提示其他/更好的响应。您是在寻找一些通用的实例化代码,还是担心必须完成抽象基类的特定设置?

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

于 2009-02-02T22:09:00.193 回答
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
  }
}

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

于 2010-05-05T19:31:22.173 回答