为什么不“在对象构造函数内部实例化新对象"? [英] Why not "instantiate a new object inside object constructor"?

查看:100
本文介绍了为什么不“在对象构造函数内部实例化新对象"?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我回答了一个问题(链接),我在另一个类的构造函数中使用了新对象的创建,此处为示例:

I answered a question (link) that I used a creation of the new object in another class' constructor, here the example:

class Person {
  public $mother_language;

  function __construct(){ // just to initialize $mother_language
    $this->mother_language = new Language('English');
}

我收到了用户"Matija"(他的个人资料)的评论,他写道:您应该永远不要在对象构造器内部实例化新对象,而是应该从外部推送依赖项,因此使用此类的任何人都知道此类依赖于什么!

And I got the comment from user "Matija" (his profile) and he wrote: You should never instantiate a new object inside object consturctor, dependencies should be pushed from outside, so anyone who uses this class knows what is this class dependent on!

总的来说,我可以同意这一点,并且我理解他的观点.

Generally, I can agree with this, and I understand his point of view.

但是,我以前经常以这种方式进行操作,例如:

However, I used to do this this way very often, for example:

  • 其他类为私有属性提供了我无法解决的功能,例如,我可以创建一个对象列表(实现ArrayAccess接口的类),并且该类将在另一个类中使用,有这样的对象列表,
  • 某些类使用例如DateTime对象,
  • 如果我是include(或自动加载)相关类,则应该没有错误的问题,
  • 因为依赖对象的数量可能很大,因此将它们全部传递给类构造函数可能会很长且不清楚,例如

  • as the private properties other classes give me functionality that I can solve not duplicating the code, for example I can create a list (class implementing ArrayAccess interface) of objects), and this class would be used in another class, that has such a list of objects,
  • some classes use for example DateTime objects,
  • if I include (or autoload) dependant class, one should have no problem with errors,
  • because dependant objects can be very large number, passing all of them to the class constructor can be very long and not clear, example

$color = new TColor('red'); // do we really need these lines?
$vin_number = new TVinNumber('xxx');
$production_date = new TDate(...);
...
$my_car = new TCar($color, $vin_number, $production_date, ...............);

  • 当我出生"在帕斯卡,然后在德尔福时,我从那里有了一些习惯.在Delphi(和FreePascal作为竞争对手)中,这种做法非常常见.例如,有一个处理字符串数组的TStrings类,并且不使用array来存储它们,而另一个类TList提供了一些有用的方法,而TStrings只是某种类型接口. TList对象是私有声明的,除了TStrings的getter和setter方法之外,没有其他访问权限.

  • as I was "born" in Pascal, then in Delp I have some habits from there. And in Delphi (and FreePascal as its competitor) this practice is very often. For example, there is a TStrings class that handles array of strings, and to store them it does not use arrays but another class, TList, that provides some useful methods, while TStrings is only some kind of interface. The TList object is private declared and has no access from outside but the getters and setters of the TStrings.

    请解释一下,避免在构造函数中创建对象真的很重要吗?

    Please explain me, is it really important to avoid creating objects in constructors?

    我已阅读此讨论,但仍然头脑不清楚.

    I've read this discussion but have still unclear mind.

    推荐答案

    是的.然后,您就清楚了对象需要构造什么.传递的大量依赖对象是一种代码味道,也许您的类做得太多,应该将其分解为多个较小的类.

    Yes it really is. You are then clear about what the object needs in order to be constructed. A large number of dependent objects being passed in is a code smell that perhaps your class is doing too much and should be broken in up in multiple smaller classes.

    如果要测试代码,则传入依赖对象的主要优点是.在您的示例中,我不能使用伪造的Language类.我必须使用实际的课程来测试Person.现在,我无法控制语言的行为以确保Person正常工作.

    The main advantage of passing in dependent objects comes if you want to test your code. In your example, I cannot use a fake Language class. I have to use the actual class to test Person. I now cannot control how Language behaves to make sure that Person works correctly.

    这篇文章有助于解释为什么这是一件坏事,以及它可能引起的潜在问题. http://misko.hevery.com/code-reviewers-guide/flaw -constructor-does-real-work/

    This post helps explain why this is a bad thing and the potential problems that it causes. http://misko.hevery.com/code-reviewers-guide/flaw-constructor-does-real-work/

    更新

    UPDATE

    除了进行测试之外,传入依赖对象还可以使您的代码更加显式,灵活和可扩展.引用我链接到的博客文章:

    Testing aside, passing in dependent objects also makes your code more explicit, flexible and extensible. To quote the blog post that I linked to:

    将协作者的构造与初始化混合在一起时,它表明只有一种配置类的方法,这会关闭否则可能会存在的重用机会.

    When collaborator construction is mixed with initialization, it suggests that there is only one way to configure the class, which closes off reuse opportunities that might otherwise be available.

    在您的示例中,您只能创建以英语"为语言的人.但是,当您想创建一个会说法语"的人时,该怎么办?我无法定义.

    In your example, you can only create people that have "English" as a language. But what about when you are wanting to create someone who speaks "French". I can't define that.

    关于创建对象并将它们传递进来,这就是Factory模式 http://的全部目的www.oodesign.com/factory-pattern.html .它将创建依赖关系并为您注入它们.因此,您可以向它询问要以所需方式初始化的对象. Person对象不必决定需要做什么.

    As for creating the objects and passing them in, that is the whole purpose of the Factory pattern http://www.oodesign.com/factory-pattern.html. It would create the dependencies and inject them for you. So you would be able to ask it for the object that would be initialized in the manner that you want. The Person object should not have to decide what it needs to be.

    这篇关于为什么不“在对象构造函数内部实例化新对象"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆