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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/504977/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 05:58:48  来源:igfitidea点击:

Why can't I create an abstract constructor on an abstract C# class?

c#inheritanceoopconstructorabstract-class

提问by Anthony D

I am creating an abstract class. I want each of my derived classes to be forced to implement a specific signature of constructor. As such, I did what I would have done has I wanted to force them to implement a method, I made an abstract one.

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

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

However I get a message saying the abstract modifier is invalid on this item. My goal was to force some code like this.

但是,我收到一条消息,说该项目的抽象修饰符无效。我的目标是强制执行一些这样的代码。

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

This is all C# .NET code. Can anyone help me out?

这都是 C# .NET 代码。谁能帮我吗?

Update 1

更新 1

I wanted to add some things. What I ended up with was this.

我想补充一些东西。我最终得到的是这个。

private A() { }

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

That does what some folks are saying, default is private, and the class needs to implement a constructor. However that doesn't FORCE a constructor with the signature A(int a, int b).

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

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


    }
}

Update 2

更新 2

I should be clear, to work around this I made my default constructor private, and my other constructor protected. I am not really looking for a way to make my code work. I took care of that. I am looking to understand why C# does not let you do this.

我应该清楚,为了解决这个问题,我将我的默认构造函数设为私有,而我的其他构造函数则受到保护。我并不是真的在寻找使我的代码工作的方法。我照办了。我想了解为什么 C# 不允许您这样做。

采纳答案by Tamas Czinege

You cannot have an abstract constructor because abstract means you must override it in any non-abstract child class and you cannot override a constructor.

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

If you think about it, this makes sense, since you always call the constructor of the child class (with the new operator) and never the base class.

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

Generally speaking, the only way in C# to enforce a specific constructor signature is by using the new()generic constraint, which enforces the existence of a parameterless constructor for the type parameter.

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

回答by Jamie Penney

Change that constructor in class A to

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

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

Then your subclasses will have to use it, as there is no default constructor.

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

They can, however, still change the actual signature of the constructor. There is no way of forcing a subclass to use a specific signature for its constructor as far as I know. I'm pretty sure constructors can't be abstract.

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

What exactly do you need this for? We might be able to suggest a work around for this.

你到底需要这个做什么?我们或许可以为此提出解决办法。

回答by devio

You cannot enforce constructor signature, as each derived class may (must!) define its own constructor(s), and they may take any parameters they like.

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

If you need to pass a given set of variables to an object of a derived class, define an abstract method which needs to be implemented by derived classes. If the classes do not implement the abstract method, you will get a compiler error.

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

回答by Simon Groenewolt

All subclasses always can specify their own constructor as long as they call a constructor of the superclass - so there is no way of forcing the a class to have a specific constructor (At least, that is the way it works in Java). You could see of using a factory pattern will get you somewhere - you could define a factory method in an interface - but you'll need a separate factory class as your abstract base class does not know the actual class of the object that needs to be created.

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

However: maybe adding a more concrete example of the issue you are having might prompt other/better responses. Are you looking for some generic instantiation code, or are you concerned specific settings on the abstract base class have to be done?

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

If you are just concerned about initialization that has to be done by the abstract class, create a method to do so, and document the usage of that method.

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

回答by mo.

not sure if this helps - but i feel this would be a solution to your 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
  }
}

with the result that you can call a constructor with the required arguments in any derived class with the correct behaviour.

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

回答by John Saunders

Although you can't override constructors, and therefore can't define an abstract constructor, you can place an abstract factory method in your abstract base class. All the derived classes would need to override that.

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

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

回答by Mats

Multiple reasons:

多种原因:

1) Constructors are not inherited thus you cannot override them.

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

2) The constructor is a static member function since it dont need a specific instance to be called. Abstract implies "virtual" which means that the implementation can vary depending on how a specific instance is subclassed, which is the opposite of the intention of the meaning of the "static" keyword.

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

回答by bresleveloper

hope this will help someone newb as i am i was looking to make a "normal" public class with a ctor that takes argument and then i needed to make it a child class so i needed an empty ctor for it.

希望这会帮助一些新手,因为我正在寻找一个带有参数的 ctor 的“普通”公共类,然后我需要将它设为子类,所以我需要一个空的 ctor。

i didnt know this before: if you make a protected ctor then the child class sees it but the rest of the program dont see it (i guess my confusion is since in asp.net i see all the protected in the aspx page which inherits from the cs...)

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