Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 构造函数与继承_C#_Oop_Inheritance - Fatal编程技术网

C# 构造函数与继承

C# 构造函数与继承,c#,oop,inheritance,C#,Oop,Inheritance,让我们以C语言为例# 现在,除了构造函数之外,Foo的所有公共成员都可以在Bar中访问。 我不能做这样的事 Bar bb = new Bar(1); 为什么构造函数是不可继承的 更新 我知道我们可以链接构造函数,但我想知道为什么上面的构造是无效的。我相信这应该有一个合理的理由。它们是(通过链接),您必须在派生对象中链接构造函数。。即: public class Foo { public Foo() { } public Foo(int j) { } } public clas

让我们以C语言为例#

现在,除了构造函数之外,Foo的所有公共成员都可以在Bar中访问。 我不能做这样的事

Bar bb = new Bar(1);
为什么构造函数是不可继承的

更新

我知道我们可以链接构造函数,但我想知道为什么上面的构造是无效的。我相信这应该有一个合理的理由。

它们是(通过链接),您必须在派生对象中链接构造函数。。即:

public class Foo
{
    public Foo() { }
    public Foo(int j) { }
}

public class Bar : Foo
{
    public Bar() : base() { }
    public Bar(int j) : base(j) { }
}
然后,派生对象中的构造函数将调用链接到基对象中的构造函数


如果您想进一步阅读,请提供更多示例。

我认为您可以执行以下操作:

public class Bar : Foo
{
  public Bar (int i)
    : base (i)
  {
  }
}

我可能有点不对劲,但这是一般的想法。

构造函数是不可继承的,因为它可能会导致奇怪和意外的行为。更具体地说,如果向基类添加新构造函数,则所有派生类都会获得该构造函数的实例。在某些情况下,这是一件坏事,因为可能基类指定的参数对派生类没有意义

一个常见的例子是,在许多语言中,所有对象(通常称为“Object”)的基类都有一个没有参数的构造函数。如果构造函数是继承的,这意味着所有对象都有一个无参数构造函数,并且不能说“我希望创建此类实例的人提供参数X、Y和Z,否则他们的代码不应该编译。”对于许多类来说,为其正确的功能定义某些参数很重要,使构造函数不可遗传是类作者可以保证某些参数总是被定义的方法的一部分

编辑以响应注释:Ramesh指出,如果构造函数是按他希望的方式继承的,他总是可以在每个派生类中使用私有声明的构造函数重写基类构造函数。这当然是事实,但这一战略存在后勤问题。它要求派生类的编写者必须密切关注基类,如果他们想要基类构造函数的块继承,就必须添加一个私有构造函数。对于编写派生类的人来说,这不仅是一项繁重的工作,而且跨类的这种隐式依赖正是导致奇怪行为的原因

Ramesh——并不是说你所描述的东西不可能添加到语言中。一般来说,这样做是不可行的,因为这种行为可能会让人困惑,并导致大量额外的调试和代码编写


Quintin Robinson在评论中对此问题提供了一些非常有价值的回答,这些回答绝对值得一读。

由于设计原因,构造函数是不可继承的。(请注意,我所知道的每种面向对象语言的情况都是一样的。)简单的答案是,在许多情况下,您确实不希望使用与基类相同的构造函数。有关更完整的解释,请参阅。

简单的答案是,该语言不是这样工作的

你真正要问的是为什么它不这样工作:-它是一个任意的选择,它是从C++和java中继承的(还有很多可能影响C语言的其他语言)。


可能的原因是,编译器只会生成一个不带参数的构造函数,并且只调用父类,这是因为如果您想要的比编译器让您自己做的更多。这是最好的选择,因为很有可能您不仅仅是在调用父构造函数。

您可能会在类中引入构造函数的一个原因是,如果该类的实例没有特定的“依赖项”,则没有任何意义。例如,它可能是一个必须连接到数据库的数据访问类:

public class FooRepository
{
    public FooRepository(IDbConnection connection) { ... }
}
如果基类中的所有公共构造函数都可用,则存储库类的用户将能够使用System.Object的默认构造函数创建类的无效实例:

var badRepository = new FooRepository();
默认情况下隐藏继承的构造函数意味着您可以强制执行依赖项,而不用担心用户创建“无效”实例。

一些讨论


其基本思想是尽可能多地控制造物主。你可以有私人基地。那么您是如何创建对象的?

构造函数只能知道如何初始化一个Foo对象,所以它也应该知道如何初始化任何潜在的子类是没有意义的

public class Bar : Foo
{
public Bar(int i) : base(i) { }
}

构造器讲述的故事是:“嘿,基类,请做任何你需要做的工作,以保持良好的状态,这样我就可以继续正确地设置自己了。”

假设构造器是可继承的。在许多情况下,如果继承的构造函数对于子类没有意义,您将如何禁用它们


语言设计者没有使用阻止继承的机制使语言复杂化,而是选择简单地使构造函数不可继承。

实际上,这是因为父构造函数不会完全初始化子对象。在这方面,构造函数是一种个人的东西。这就是大多数语言不继承构造函数的原因。

我确实理解链接,但我的示例无效的原因是我想理解的(我更新了问题以突出显示相同的内容)。我明白了,很抱歉回答了一个你没有问到的问题,我想我读得有点太远了。谢谢Quintin,你的问题让我思考了一下+我确实理解链接,但我想理解的是为什么我的示例无效(我更新了问题以突出显示相同的内容)。如果你向基类添加构造函数,你将能够初始化仅在该类中存在的内容,这是一个好行为,我不是
public class Bar : Foo
{
public Bar(int i) : base(i) { }
}