为什么要在构造函数中初始化成员变量?
当我第一次开始使用面向对象的编程语言时,我被教导了以下规则:
在类中声明字段时,先不要初始化它。 在构造函数中执行此操作。
C# 中的一个例子:
public class Test
{
private List<String> l;
public Test()
{
l = new List<String>();
}
}
但是当最近有人问我为什么要这样做时,我无法说出原因。 我不太熟悉 C#(或其他编程语言,就此而言,因为我相信这可以在所有 OO 语言中完成)的内部工作原理。
那么为什么要这样做呢? 是安全吗? 特性?
When I first started working with object-oriented programming languages, I was taught the following rule:
When declaring a field in a class, don't initialize it yet. Do that in the constructor.
An example in C#:
public class Test
{
private List<String> l;
public Test()
{
l = new List<String>();
}
}
But when someone recently asked me why to do that, I couldn't come up with a reason.
I'm not really familiar with the internal workings of C# (or other programming languages, for that matter, as I believe this can be done in all OO languages).
So why is this done? Is it security? Properties?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果您有多个构造函数,您可能希望将字段初始化为不同的值
当您在构造函数中初始化字段时,对于构造函数的其余部分而言,它的确切初始化时间不会产生混淆。 对于单个类来说,这似乎微不足道,但当您有一个继承层次结构,并且构造函数代码在每个级别运行并访问超类字段时,这似乎微不足道。
If you have multiple constructors, you might want to initialize a field to different values
When you initialize the field in the constructor, there can be no confusion over when exactly it is initialized in regard to the rest of the constructor. This may seem trivial with a single class, but not so much when you have an inheritance hierarchy with constructor code running at each level and accessing superclass fields.
C# 编译器将采用您内联执行的任何非静态成员初始化并将其移至构造函数中。 换句话说,这个:
被编译成这样:
我不确定其他语言的编译器如何处理这个问题,但就 C# 而言,这是一个风格问题,你可以自由地做任何你想做的事。 请注意,静态字段的处理方式有所不同: 阅读本文更多相关信息。
The C# compiler will take any non-static member intialization that you do inline and move it into the constructor for you. In other words this:
gets compiled to this:
I am not sure how compilers for other languages handle this but as far as C# is concerned it is a matter of style and you are free to do whichever you wish. Please note that static fields are handled differently: read this article for more information on that.
这样做的原因之一是它将所有初始化代码放在一个位置,方便其他人阅读您的类。 话虽如此,我并没有真正这样做,有两个主要原因。 (1) 我使用 TDD/单元测试来定义我的类的行为。 如果您想知道无参数构造函数的作用,您应该真正阅读我在无参数构造函数上构建的测试。 (2) 在 C# 3.0 中,我通常使用自动属性和内联初始化以及无参数构造函数来实例化对象。 这更加灵活,并且它将属性的定义与代码的使用位置保持一致。 这将覆盖构造函数中的任何初始化,因此我很少在那里放置任何初始化。 当然,这只适用于C#。
前任。 (共 2 个)
One reason to do it is that it puts all of the initialization code in one place which is convenient for others reading your class. Having said this I don't really do it for two primary reasons. (1) I use TDD/Unit testing to define the behavior of my class. If you want to know what the parameterless constructor does, you should really read the tests I've built on the parameterless constructor. (2) With C# 3.0, I typically use automatic properties and inline initialization with a parameterless constructor to instantiate the object. This is much more flexible and it puts the definition of the properties right in line where the code is being used. This would override any initialization in the constructor so I rarely put any there. Of course, this only applies to C#.
Ex. (of 2)
有时构造函数具有用于初始化内部变量的参数。 例如数组的大小
sometimes the constructor has parameters that are used for initializing internal variables. For example size of arrays
我还没有听说过不提供这两种选择的令人信服的理由。 我怀疑真正的原因与从解析角度简化语言结构有关。 在 C 派生语言中尤其如此,其中解析赋值语句需要 75% 的语言语法规则。 在我看来,允许它并定义它如何精确地工作会很好。 我同意迈克尔的评论 关于插入继承和多个构造函数时复杂性的增加,但仅仅因为添加一个功能并不意味着您必须使用它。 我会投票支持两者,尽管我的投票并没有多大意义。
I haven't heard a compelling reason to not offer both options. I suspect that the real reason has to do with simplifying the language structure from a parsing perspective. This is especially true in C-derivative languages where parsing an assignment statement requires 75% of the language syntax rules. It seems to me that allowing it and defining how it would work precisely would be nice. I agree with Michael's comment about the complexity increase as you insert inheritance and multiple constructors but just because you add a feature doesn't mean that you have to use it. I would vote to support both even though my vote doesn't really add up to much.
我总是喜欢将类视为对象的工厂,而将构造函数视为生产线上的最后一站。 类中声明的字段是描述对象的蓝图,但是在通过调用构造函数对此类对象进行排序之前,蓝图不会被实现为对象......此外,正如有人指出的那样,在中进行所有初始化您的构造函数将提高可读性,并且它将提供初始化的动态性(它可能不是您正在处理的无参数构造函数)。
此外,在某些语言中,构造函数可用于将对象重置为原始状态,这就是为什么需要在构造函数中实例化对象的原因。
I always like to think of the class as a factory for objects, and the constructor as the final stop on the production line. The fields declared in the class are blueprints descirbing the object, but the blueprint won't be realised into an object before such an object is ordered tthrough a call to the constructor... Also, as someone pointed out, doing all your initialisations in your constructor will improve readability, as well as it wil provide for dynamicity in initialisation (it might not be a parameterless constructor you're dealing with).
Also, in some languages the constructor may be used for resetting an object to an original state, which is why it will then be necessary to instatiate the object in the constructor.