java 为什么当你用参数创建一个默认的无参数构造函数时会消失

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11792207/
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-10-31 06:23:18  来源:igfitidea点击:

Why does the default parameterless constructor go away when you create one with parameters

c#javac++default-constructor

提问by olagjo

In C#, C++ and Java, when you create a constructor taking parameters, the default parameterless one goes away. I have always just accepted this fact, but now I've started wondering why.

在 C#、C++ 和 Java 中,当您创建一个带参数的构造函数时,默认的无参数构造函数就会消失。我一直只是接受这个事实,但现在我开始想知道为什么。

What is the reason for this behavior? Is it just a "safety measure/guess" saying "If you've created a constructor of your own, you probablydon't want this implicit one hanging around"? Or does it have a technical reason that makes it impossible for the compiler to add one once you have created a constructor yourself?

这种行为的原因是什么?它只是一个“安全措施/猜测”,说“如果您已经创建了自己的构造函数,您可能不希望这个隐含的构造函数四处游荡”?或者它是否有技术原因使编译器无法在您自己创建构造函数后添加一个?

回答by Dan Puzey

There's no reason that the compiler couldn't add the constructor if you've added your own - the compiler could do pretty much whatever it wants! However, you have to look at what makes most sense:

如果您添加了自己的构造函数,则编译器没有理由不能添加构造函数 - 编译器几乎可以做任何它想做的事!但是,您必须查看最有意义的内容:

  • If I haven't defined anyconstructor for a non-static class, I most likely want to be able to instantiate that class. In order to allow that, the compiler mustadd a parameterless constructor, which will have no effect but to allow instantiation. This means that I don't have to include an empty constructor in my code just to make it work.
  • If I've defined a constructor of my own, especially one with parameters, then I most likely have logic of my own that must be executed on creating the class. If the compiler were to create an empty, parameterless constructor in this case, it would allow someone to skipthe logic that I had written, which might lead to my code breaking in all number of ways. If I want a default empty constructor in this case, I need to say so explicitly.
  • 如果我没有为非静态类定义任何构造函数,我很可能希望能够实例化该类。为了实现这一点,编译器必须添加一个无参数构造函数,该构造函数除了允许实例化之外没有任何效果。这意味着我不必在我的代码中包含一个空的构造函数来让它工作。
  • 如果我已经定义了自己的构造函数,尤其是带有参数的构造函数,那么我很可能有自己的逻辑,必须在创建类时执行。如果编译器在这种情况下创建一个空的、无参数的构造函数,它将允许某人跳过我编写的逻辑,这可能会导致我的代码以多种方式被破坏。如果在这种情况下我想要一个默认的空构造函数,我需要明确说明。

So, in each case, you can see that the behaviour of current compilers makes the most sense in terms of preserving the likely intentof the code.

因此,在每种情况下,您都可以看到当前编译器的行为在保留代码可能的意图方面最有意义。

回答by Jon Skeet

There's certainly no technical reason why the language hasto be designed this way.

语言必须以这种方式设计,这当然没有技术上的原因。

There are four somewhat-realistic options that I can see:

我可以看到四个有点现实的选项:

  1. No default constructors at all
  2. The current scenario
  3. Alwaysproviding a default constructor by default, but allowing it to be explicitly suppressed
  4. Always providing a default constructor withoutallowing it to be suppressed
  1. 根本没有默认构造函数
  2. 目前的情景
  3. 默认情况下始终提供默认构造函数,但允许显式抑制它
  4. 总是提供一个默认构造函数不允许它被抑制

Option 1 is somewhat attractive, in that the more I code the less often I reallywant a parameterless constructor. Some day I should count just how often I actuallyend up using a default constructor...

选项1是有点吸引力的,因为我越码的次数越少我真的希望有一个参数的构造函数。总有一天我应该计算我实际上最终使用默认构造函数的频率......

Option 2 I'm fine with.

选项 2 我很好。

Option 3 goes against the flow of both Java and C#, for the rest of the language. There's never anything that you explicitly "remove", unless you count explicitly making things more private than they would be by default in Java.

对于该语言的其余部分,选项 3 与 Java 和 C# 的流程背道而驰。永远不会有任何你明确“删除”的东西,除非你明确地计算让事情比 Java 中的默认设置更私密。

Option 4 is horrible - you absolutelywant to be able to force construction with certain parameters. What would new FileStream()even mean?

选项 4 太可怕了 - 您绝对希望能够使用某些参数强制构建。什么会new FileStream()甚至意味着什么?

So basically, ifyou accept the premise that providing a default constructor makes sense at all, I believe it makes a lot of sense to suppress it as soon as you provide your own constructor.

所以基本上,如果你接受提供默认构造函数完全有意义的前提,我相信一旦你提供自己的构造函数就抑制它是很有意义的。

回答by Jon Hanna

Edit. Actually, while what I say in my first answer is valid, this is the real reason.:

编辑。实际上,虽然我在第一个答案中所说的话是有效的,但这才是真正的原因。:

In the beginning there was C. C is not object-oriented (you can take an OO approach, but it doesn't help you or enforce anything).

一开始有 C。C 不是面向对象的(您可以采用 OO 方法,但它不会帮助您或强制执行任何操作)。

Then there was C With Classes, that was later renamed C++. C++ is object-oriented, and therefore encourages encapsulation, and ensuring an object's invariant - upon construction and at the beginning and end of any method, the object is in a valid state.

然后是 C With Classes,后来更名为 C++。C++ 是面向对象的,因此鼓励封装,并确保对象的不变性 - 在构造时以及在任何方法的开始和结束时,对象都处于有效状态。

The natural thing to do with this, is to enforce that a class must always have a constructor to ensure it starts in a valid state - if the constructor doesn't have to do anything to ensure this, then the empty constructor will document this fact.

自然的做法是强制一个类必须始终有一个构造函数以确保它以有效状态启动 - 如果构造函数不需要做任何事情来确保这一点,那么空构造函数将记录这一事实.

But a goal with C++ was to be compatible with C to the point that as much as possible, all valid C programs were also valid C++ programs (no longer as active a goal, and the evolution of C separate to C++ means it no longer holds).

但是 C++ 的一个目标是与 C 兼容到尽可能多的程度,所有有效的 C 程序也是有效的 C++ 程序(不再是一个积极的目标,C 的演变与 C++ 分开意味着它不再适用)。

One effect of this was the duplication in functionality between structand class. The former doing things the C way (everything public by default) and the latter doing things in a good OO way (everything private by default, developer actively makes public what they want public).

这样做的一个影响是struct和之间的功能重复class。前者以 C 方式做事(默认一切都是公开的),后者以良好的 OO 方式做事(默认一切都是私有的,开发者主动公开他们想要公开的东西)。

Another is that in order for a C struct, which couldn't have a constructor because C doesn't have constructors, to be valid in C++, then there had to be a meaning for this to the C++ way of looking at it. And so, while not having a constructor would go against the OO practice of actively ensuring an invariant, C++ took this to mean that there was a default parameterless constructor that acted like it had an empty body.

另一个原因是,为了使 Cstruct不能有构造函数,因为 C 没有构造函数,所以在 C++ 中有效,那么必须对 C++ 看待它的方式有一个意义。因此,虽然没有构造函数会违背积极确保不变量的 OO 实践,但 C++ 认为这意味着有一个默认的无参数构造函数,就像它有一个空体一样。

All C structswere now valid C++ structs, (which meant they were the same as C++ classeswith everything - members and inheritance - public) treated from the outside as if it had a single, parameterless constructor.

structs现在所有的 C都是有效的 C++ structs,(这意味着它们与 C++ 相同classes,所有的东西——成员和继承——公共)从外部对待,就好像它有一个单一的、无参数的构造函数。

If however you did put a constructor in a classor struct, then you were doing things the C++/OO way rather than the C way, and there was no need for a default constructor.

但是,如果您确实将构造函数放在 aclass或 中struct,那么您正在以 C++/OO 方式而不是 C 方式做事,并且不需要默认构造函数。

Since it served as a shorthand, people kept using it even when compatibility wasn't possible otherwise (it used other C++ features not in C).

由于它是一种速记,因此即使在其他情况下不可能兼容的情况下,人们也会继续使用它(它使用了 C 中没有的其他 C++ 特性)。

Hence when Java came along (based on C++ in many ways) and later C# (based on C++ and Java in different ways), they kept this approach as something coders may already be used to.

因此,当 Java(以多种方式基于 C++)和后来的 C#(以不同方式基于 C++ 和 Java)出现时,他们保留了这种方法,因为编码人员可能已经习惯了这种方法。

Stroustrup writes about this in his The C++ Programming Languageand even more so, with more focus upon the "whys" of the language in The Design and Evolution of C++.

Stroustrup 在他的The C++ Programming Language 中写到了这一点,甚至更多,在The Design and Evolution of C++ 中更加关注语言的“为什么” 。

=== Original Answer ===

=== 原始答案 ===

Let's say this didn't happen.

假设这没有发生。

Let's say I don't want a parameterless constructor, because I can't put my class into a meaningful state without one. Indeed, this is something that can happen with structin C# (but if you can't make meaningful use of an all-zeros-and-nulls structin C# you're at best using a non-publicly-visible optimisation, and otherwise have a design flaw in using struct).

假设我不想要一个无参数的构造函数,因为如果没有它,我就无法将我的类置于有意义的状态。事实上,这struct在 C#中可能发生(但如果你不能在 C# 中有意义地使用全零和空值struct,你充其量使用非公开可见的优化,否则有一个使用中的设计缺陷struct)。

To make my class able to protect its invariants, I need a special removeDefaultConstructorkeyword. At the very least, I'd need to create a private parameterless constructor to make sure no calling code calls the default.

为了让我的类能够保护它的不变量,我需要一个特殊的removeDefaultConstructor关键字。至少,我需要创建一个私有的无参数构造函数以确保没有调用代码调用默认值。

Which complicates the language some more. Better not to do it.

这使语言更加复杂。最好不要这样做。

In all, it's best not to think of adding a constructor as removing the default, better to think of having no constructor at all as syntactic sugar for adding a parameterless constructor that doesn't do anything.

总而言之,最好不要将添加构造函数视为删除默认值,最好将根本没有构造函数视为添加无参数构造函数的语法糖。

回答by Anders Abel

The default, parameterless constructor is added if you don't do anything yourself to take control over object creation. Once you've created a single constructor to take control, the compiler "backs off" and let you have the full control.

如果您自己没有做任何事情来控制对象创建,则会添加默认的无参数构造函数。一旦您创建了一个构造函数来获得控制权,编译器就会“退出”并让您拥有完全的控制权。

If it wouldn't be this way, you would need some explicit way of disabling the default constructor if you only want objects to be constructable through a constructor with parameters.

如果不是这样,如果您只想通过带参数的构造函数构造对象,则需要某种显式禁用默认构造函数的方法。

回答by Botz3000

I think the question should be the other way around: Why don't you need to declare a default constructor if you haven't defined any other constructors?

我认为问题应该反过来:如果您没有定义任何其他构造函数,为什么不需要声明默认构造函数?

A constructor is mandatory for non-static classes.
So i think if you haven't defined any constructors, the generated default constructor is just a convenient feature of the C# compiler, also your class wouldn't be valid without a constructor. So nothing wrong with implicitly generating a constructor that does nothing. It certainly looks cleaner than having empty constructors all around.

对于非静态类,构造函数是必需的。
所以我认为如果你没有定义任何构造函数,生成的默认构造函数只是 C# 编译器的一个方便的特性,如果没有构造函数,你的类也不会有效。所以隐式生成一个什么都不做的构造函数没有错。它看起来肯定比到处都是空的构造函数更干净。

If you have already defined a constructor, your class is valid, so why should the compiler assume you want a default constructor? What if you don't want one? Implement an attribute to tell the compiler to not generate that default constructor? I don't think that would be a good idea.

如果你已经定义了一个构造函数,你的类是有效的,那么编译器为什么要假设你需要一个默认的构造函数呢?如果你不想要一个怎么办?实现一个属性来告诉编译器不要生成那个默认构造函数?我不认为那是个好主意。

回答by mw_21

It's a convenience function of the compiler. If you define a Constructor with parameters but don't define a parameterless constructor, the possibility that you don't want to allow a parameterless constructor is much higher.

这是编译器的一个便利功能。如果你定义了一个带参数的构造函数但没有定义一个无参数的构造函数,那么你不想允许一个无参数的构造函数的可能性要高得多。

This is the case for many objects that just don't make sense to initialize with an empty constructor.

对于许多用空构造函数初始化没有意义的对象来说就是这种情况。

Otherwise you'd have to declare a private parameterless constructor for each class that you want to restrict.

否则,您必须为要限制的每个类声明一个私有的无参数构造函数。

In my opinion it's not good style to allow a parameterless constructor for a class that needs parameters to function.

在我看来,为需要参数才能起作用的类允许使用无参数构造函数并不是一种好风格。

回答by ashes

The default constructor can be constructed only when the class doesn't have a constructor. Compilers are written in such a way as to provide this only as a backup mechanism.

只有当类没有构造函数时才能构造默认构造函数。编译器的编写方式仅将其作为备份机制提供。

If you have a parameterized constructor, you may not want an object to be created using the default constructor. Had the compiler provided a default constructor, you would have had to write a no-arg constructor and make it private in order to prevent objects being created using no arguments.

如果您有参数化构造函数,您可能不希望使用默认构造函数创建对象。如果编译器提供了默认构造函数,您将不得不编写一个无参数构造函数并将其设为私有,以防止使用无参数创建对象。

Also, there would be higher chances of you forgetting disabling, or 'privatising' the default constructor, and thereby causing a potential functional error hard to catch.

此外,您更有可能忘记禁用或“私有化”默认构造函数,从而导致难以捕捉的潜在功能错误。

And now you have to explicitly define a no-arg constructor if you'd like an object to be created either the default way or by passing parameters. This is strongly checked, and the compiler complains otherwise, thereby ensuring no loophole here.

现在,如果您希望以默认方式或通过传递参数来创建对象,则必须明确定义无参数构造函数。这是经过严格检查的,否则编译器会抱怨,从而确保这里没有漏洞。

回答by Zaid Masud

Premise

前提

This behaviour can be seen as a natural extension of the decision for classes to have a default public parameterless constructor. Based on the question that's been asked we take this decision as a premise and assume that we are not questioning it in this instance.

这种行为可以看作是类具有默认公共无参数构造函数决定的自然扩展。基于所提出的问题,我们将这一决定作为前提,并假设我们在本例中不会质疑它。

Ways to Remove Default Constructor

删除默认构造函数的方法

It follows that there must be a way to remove the default public parameterless constructor. This removal could be accomplished in the following ways:

因此,必须有一种方法可以删除默认的公共无参数构造函数。这种移除可以通过以下方式完成:

  1. Declare a non-public parameterless constructor
  2. Automatically remove the parameterless constructor when a constructor with parameters is declared
  3. Some keyword / attribute to indicate to the compiler to remove the parameterless constructor (awkward enough that it is easy to rule out)
  1. 声明一个非公共的无参数构造函数
  2. 声明带参数构造函数时自动移除无参数构造函数
  3. 一些关键字/属性来指示编译器删除无参数构造函数(很尴尬,很容易排除)

Selecting the Best Solution

选择最佳解决方案

Now we ask ourselves: If there is no parameterless constructor, what must it be replaced by?and Under what types of scenarios would we want to remove the default public parameterless constructor?

现在我们问自己:如果没有无参数构造函数,它必须用什么代替?并且将我们想要在什么类型的场景删除默认的公共参数构造函数?

Things start to fall in place. Firstly, it must either be replaced with a constructor with parameters, or with a non-public constructor. Secondly, the scenarios under which you do not want a parameterless constructor are:

事情开始就位。首先,它必须要么替换为带参数的构造函数,要么替换为非公共构造函数。其次,您不想要无参数构造函数的情况是:

  1. We do not want the class to be instantiated at all, or we want to control the visibility of the constructor: declare a non-public constructor
  2. We want to force parameters to be provided on construction: declare a constructor with parameters
  1. 我们根本不希望类被实例化,或者我们想控制构造函数的可见性:声明一个非公共构造函数
  2. 我们想强制在构造时提供参数声明一个带参数的构造函数

Conclusion

结论

There we have it -- exactly the two ways that C#, C++ and Java allow the removal of the default public parameterless constructor.

我们有了它——正是 C#、C++ 和 Java 允许删除默认公共无参数构造函数的两种方式。

回答by PQubeTechnologies

I think this is handled by the compiler. If you open the .netassembly in ILDASMyou will see the default constructor, even if it is not in the code. If you define a parameterized constructor the default constructor will not bee seen.

我认为这是由编译器处理的。如果您在其中打开.net程序集,ILDASM您将看到默认构造函数,即使它不在代码中。如果您定义参数化构造函数,则将看不到默认构造函数。

Actually when you define the class (non static), the compiler provides this feature thinking that you will be just creating an instance. And if you want any specific operation to perform you surely will be having your own constructor.

实际上,当您定义类(非静态)时,编译器会提供此功能,认为您将只是创建一个实例。如果您想要执行任何特定操作,您肯定会拥有自己的构造函数。

回答by Jaider

A class need a constructor. It is mandatory requirement.

一个类需要一个构造函数。这是强制性要求。

  • If you don't create one, parameterless constructor will be given to you automatically.
  • If you don't want a parameterless constructor, then you need to create your own.
  • If you need both, parameterless constructor and parameter based-constructor you can add them manually.
  • 如果你不创建一个,无参数构造函数将自动给你。
  • 如果您不想要无参数构造函数,那么您需要创建自己的构造函数。
  • 如果您同时需要无参数构造函数和基于参数的构造函数,您可以手动添加它们。

I will answer you question with another, why do we want always a default parameterless constructor? there are case where this is not desired, so the developer has the control to add or remove it as is need.

我会用另一个来回答你的问题,为什么我们总是想要一个默认的无参数构造函数?在某些情况下这是不希望的,因此开发人员可以根据需要控制添加或删除它。