为什么构造函数是邪恶的?

时间:2011-05-03 19:41:30

标签: c# java constructor

我记得读过一篇关于构造者是邪恶的文章(但不能放置它)。作者提到构造函数是一种特殊的方法;但有限制(例如他们不能有返回值)。

施工人员是邪恶的吗?没有构造函数,而是依赖Initialize之类的方法,以及成员变量的默认值,这样更好吗?

(如果你必须确定一种语言,你的答案可以特定于C#或Java。)

13 个答案:

答案 0 :(得分:6)

听起来像艾伦·霍洛布。有人可能会说,构造函数 evil 仅仅是为了驱动网络流量:)它们并不比任何其他语言构造更邪恶。他们有好的和坏的影响。当然你无法消除它们 - 如果没有它们就无法构建对象!

但是你可以做什么,艾伦正在制作这种情况,你是否可以限制你对它们的实际调用,而是在合情合理的情况下支持像Initialize这样的工厂方法。原因很简单:它减少了类之间的耦合,并且在测试期间或应用程序发展过程中更容易将一个类替换为另一个类。

想象一下,如果您的应用程序执行类似

的操作
DatabaseConnection dc = new OracleDatabaseConnection(connectionString);
dc.query("...");

并想象这会在您的应用程序中的一百个位置发生。现在,你如何对任何这样做的类进行单元测试?当你切换到Mysql以省钱时会发生什么?

但如果你这样做了:

DatabaseConnection dc = DatabaseConnectionFactory.get(connectionString);
dc.query("...");

然后要更新您的应用,您只需更改DatabaseConnectionFactory.get()返回的内容,并且可以通过配置文件进行控制。避免明确使用构造函数可以使代码更加灵活。

编辑:我找不到“构造函数”文章,但这里是他的extends is evil文章,这是他的getters and setters are evil文章。

答案 1 :(得分:3)

他们不是。实际上,有一种称为控制反转的特定模式,它巧妙地使用了构造函数来很好地分离代码并使维护更容易。此外,某些问题只能通过使用非默认构造函数来解决。

答案 2 :(得分:2)

恶?否。

调用构造函数确实需要调用“new”,这会将您绑定到特定的实现。工厂和依赖注入允许您对运行时类型更加动态,但它们需要对接口进行编程。

我认为后者更灵活,但建构者更邪恶?这太过分了,就像为一切都做得太过分了。

答案 3 :(得分:2)

构造函数不是邪恶的,但(至少在Java中)通常最好使用静态Factory方法(当然在内部使用构造函数)。

以下是来自Effective Java的一些引用,第1项:考虑使用静态工厂方法而不是构造函数

  

静态工厂的一个优势   方法是,与构造函数不同,   他们有名字。如果参数为   一个构造函数不在,和   他们自己,描述对象   返回,一个带有静态的工厂   精心挑选的名称更易于使用   生成的客户端代码更容易   读取。

...

  

静态工厂的第二个优势   方法是,与构造函数不同,   他们不需要创建新的   每次调用它们的对象。这个   允许不可变类(第15项)   使用预构建的实例,或   缓存实例,因为它们是   建造并分发它们   反复避免创造   不必要的重复对象。

...

  

静态工厂的第三个优势   方法是,与构造函数不同,   他们可以归还任何一个对象   返回类型的子类型。

...

  

静态工厂的第四个优势   方法是他们减少了   创建参数化的详细程度   类型实例。不幸的是,你   必须在何时指定类型参数   你调用一个的构造函数   参数化的类,即使它们是   从背景来看很明显这通常   要求您提供类型   参数快速连续两次:

Map<String, List<String>> m =
new HashMap<String, List<String>>();

...

  

提供的主要缺点   只有静态工厂方法才是   没有公共或受保护的课程   构造函数不能被子类化。

...

  

静态的第二个缺点   工厂方法是他们不是   容易与其他人区别开来   静态方法。

答案 4 :(得分:1)

构造函数允许初始化列表和其他有用的东西。没有复制构造函数,就无法动态初始化数组中的对象(不使用指向对象的指针)。

不,他们不是邪恶的。

他们是特例。

答案 5 :(得分:1)

构造者邪恶。它们的存在使得在初始化类的实例时可以运行代码。正如任何其他编程概念一样,如果它们没有得到正确使用,它们可能会成为一种灾难。但是,如果使用得当,它们可能是一个伟大的(必不可少的)工具。

http://en.wikipedia.org/wiki/Constructor_(object-oriented_programming

答案 6 :(得分:0)

我不会说施工人员是邪恶的。

构造函数返回对您正在实例化的Object的引用,应该用于将对象设置为默认状态。我可以看到使用Initialize方法的好处,但没有多大意义。除非你需要在对象被分配了堆栈空间和初始值之后初始化一些逻辑。

答案 7 :(得分:0)

构造者邪恶。无论你读什么文章都是错的,你最好忘记链接。

答案 8 :(得分:0)

建筑师不是邪恶的,也不是好的。如果正确使用并且在正确的上下文中,构造函数是一个非常有用的工具。事实上,至少在.NET语言(如C#)中如果没有在代码中显式声明构造函数,编译器将为您创建一个没有功能的构造函数。

答案 9 :(得分:0)

遵循正常的OO编程范例时,构造函数很好。在某些情况下,您可能需要对如何创建对象设置额外的约束,因此在某些情况下,具有私有ctors的Factory模式可能更适合。还有一种哲学/最佳实践,即对象实例化应该与初始化相同,在这种情况下,构造函数是您工厂外唯一真正的选择。

(工厂当然还在内部使用构造函数)

答案 10 :(得分:0)

问题可能不是Java或C#中的构造函数,而是javascript中的构造函数。在Javascript中,构造函数可能是微妙错误的来源。很多Javascript书籍都建议初学者避开构造函数。

有关构造函数的恶意和新关键字的更详细讨论,请在javascript中查看:Is JavaScript's "new" keyword considered harmful?

答案 11 :(得分:0)

我在某种程度上从MiškoHevery的谈话“不要找东西”中找到了这种氛围,这可以在YouTube上找到。他给出的部分概述讨论,我解释为对“胖子”的批评,如果不是一般的构造者。

至少在我理解的情况下,这个论点的意义在于,接受对象所需内容的构造函数鼓励您使用构造函数强制执行正确性,而不是通过测试强制执行。构造函数确实倾向于臃肿做到这一点,所以如果这困扰你,你可以认为它是构造函数概念中的邪恶条纹。在谈话中,他说他更喜欢只需要一个物体在需要做某事时“拥有”另一个物体,而不是在施工时要求它。

答案 12 :(得分:0)

这是一篇有关构造函数是否有害的文章,而不是“邪恶的”文章。它主要是在JavaScript / Es6的上下文中使用的,但参数可能适用于任何具有构造函数的语言。

该参数实际上是关于用户定义的构造函数的,您仍然需要调用系统提供的默认构造函数,否则根本无法创建任何实例。

最简单的论据是,如果您可以使用静态方法执行与自定义构造函数相同的操作,那么最好选择其中一种方法并始终遵循该方法,除非有特殊原因除外。

这使您的程序更简单,因此更不容易出错。请注意,Smalltalk从来没有“构造函数”。

https://medium.com/@panuviljamaa/constructors-considered-harmful-c3af0d72c2b1