C# 继承和默认构造函数
Posted
技术标签:
【中文标题】C# 继承和默认构造函数【英文标题】:C# inheritance and default constructors 【发布时间】:2015-07-09 16:33:07 【问题描述】:假设有一个基类A
和一个派生自A
的类B
。
然后,我们知道类A
的构造函数永远不会被类B
继承。但是,当创建B
的新对象时,在调用B
类的默认/自定义构造函数之前调用类A
的默认构造函数。可能这样做的目的是A
类的字段需要初始化为默认值。
现在,假设 A
类定义了一个自定义构造函数。这意味着类A
的默认构造函数被编译器静默删除。现在,在创建类B
的新实例时,在调用类B
的构造函数之前会自动调用类A
的哪个构造函数? (在这种情况下,A
类字段如何初始化?)
【问题讨论】:
我没有意识到 OOPS 是面向对象编程 S*。不建议编辑,因为我喜欢将其视为"oops"。 @PeterMortensen 这应该是什么完全相同的副本? 已经回滚了删除 c# 标签的编辑,并且为了清楚起见还编辑了主题行。这绝对是一个特定于语言的问题。 【参考方案1】:现在,在创建类
B
的新实例时,在调用类B
构造函数之前会自动调用类A
的哪个构造函数?
基本上,代码将无法编译。每个构造函数都必须隐式或显式链接到另一个构造函数。它链接的构造函数可以在同一个类(this
)或基类(base
)中。
这样的构造函数:
public B()
是隐含的:
public B() : base()
...如果您根本没有指定构造函数,它将以相同的方式隐式添加 - 但它仍然必须有一些东西可以调用。例如,您的场景:
public class A
public A(int x)
public class B : A
导致编译器错误:
错误 CS7036:没有给出与
'A.A(int)'
的所需形参'x'
对应的参数
但是,您可以显式指定不同的构造函数调用,例如
public B() : base(10) // Chain to base class constructor
或
public B() : this(10) // Chain to same class constructor, assuming one exists
【讨论】:
在 A 类中指定一个显式的空构造函数会消除错误吗? @helloworld:一个无参数的?绝对地。您链接到的构造函数不必由编译器隐式引入 - 它可以是普通的无参数构造函数。或者它甚至可以是一个只有可选参数的,或者只是一个params
参数。基本上,只要: base()
可以工作,就可以了。
这是什么编程语言?
@TobiasFeil:C# - 最初在问题标签中,但被另一个用户编辑掉了。【参考方案2】:
向class A
提供自己的构造函数后,在class B
对象创建期间不会发生自动调用。
class B
构造函数中的第一行应该是super(paramsToClassAConstructor)
,或者可以使用this()
在class B
中调用另一个构造函数。在这种情况下,class B
中的第二个构造函数负责调用 class A
构造函数。
【讨论】:
你写的适用于Java,但问题被标记为C#,它有不同的规则。 天哪..我没有看标签..谢谢你睁大眼睛:)【参考方案3】:当构造函数完成执行时 - 对象处于有效的初始状态。我们应该使用有效的对象。 当我们为 A 类提供一个非默认构造函数时 - 我们实际上是在说 - 构造 A 类对象,即处于有效的初始状态 - 我们需要更多信息 - 这是由参数提供的。 鉴于此,编译器通过不生成默认构造函数来提供帮助。客户端代码将无法编译(因为它应该 - 我们如何让对象处于有效状态?) - 客户端程序员将不得不坐起来注意。 当您提供显式的空构造函数时 - 您实际上是在告诉编译器 - 我知道我在做什么 - 默认构造函数很可能会将字段初始化为一些合理的默认值。 或者促进重用 - 默认构造函数可以调用具有一些默认值的非默认构造函数。 子类知道它的超类 - 子类构造函数可以调用超类方法 - (子类中一些通常重用的方法)。鉴于上述情况 - 这要求超类部分应处于有效状态 - 即其构造函数在其任何方法调用之前执行。这需要在子类构造函数之前调用超级构造函数。 鉴于此 - 您将能够轻松设计构造函数以强制执行正确的初始状态行为。
【讨论】:
【参考方案4】:没有定义基类参数构造函数的特殊规则。规则与其他类构造函数相同。您可以按如下方式定义构造函数的数量:
class baseclass
public baseclass()
public baseclass(string message)
如果基类有构造函数,则需要子类或派生类从其基类调用构造函数。
class childclass : baseclass
public childclass()
public childclass(string message)
: base(message)
【讨论】:
以上是关于C# 继承和默认构造函数的主要内容,如果未能解决你的问题,请参考以下文章