当前位置: 首页 > 知识库问答 >
问题:

为什么不“在对象构造函数中实例化一个新对象”呢?

班展
2023-03-14

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

class Person {
  public $mother_language;

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

我得到了用户“Matija”(他的个人资料)的评论,他写道:你永远不应该在object consturctor中实例化一个新对象,依赖项应该从外部推送,所以任何使用这个类的人都知道这个类依赖于什么!

>

  • 由于私有属性,其他类给了我一些功能,我可以在不重复代码的情况下解决这些功能,例如,我可以创建一个对象列表(实现ArrayAccess接口的类),这个类将用于另一个具有这样一个对象列表的类,
  • 某些类使用例如datetime对象,
  • 如果我包含(或自动加载)依赖类,那么错误应该没有问题,
  • 由于依赖对象的数量可能非常大,因此将所有依赖对象传递给类构造函数可能非常长且不清楚,例如

    $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, ...............);
    

    因为我“出生”在帕斯卡,然后在德尔菲,我有一些习惯从那里。而在德尔福(以及它的竞争对手FreePascal)中,这种做法是非常常见的。例如,有一个TStrings类处理字符串数组,为了存储它们,它不使用array,而是另一个类TList,它提供了一些有用的方法,而TStrings只是某种接口。tlist对象是私有声明的,除了tstrings的getter和setter之外,没有外部访问权限。

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

    我读了这篇讨论,但仍然不清楚。

  • 共有1个答案

    花阳秋
    2023-03-14

    是的。真的是。然后,您就清楚了对象需要什么来构造。传入大量的依赖对象是一种代码气味,可能您的类做得太多了,应该在多个较小的类中分解。

    如果要测试代码,传入依赖对象的主要好处是。在你的例子中,我不能使用假语言类。我必须使用实际的类来测试人。我现在不能控制语言的行为来确保这个人正确地工作。

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

    至于创建对象并将它们传入,这就是Factory模式http://www.oodesign.com/factory-pattern.html的全部用途。它将创建依赖项并为您注入它们。因此,您可以向它请求以您想要的方式初始化的对象。Person对象不应该决定它需要是什么。

     类似资料:
    • 问题内容: 如何从Java的构造函数中获取实例化对象? 我想为某些GUI类存储对父对象的引用,以模拟事件冒泡-调用父处理程序-但我不想更改所有现有代码。 问题答案: 简短的回答:Java没有办法做到这一点。(您可以找到哪个班级叫您,但以下较长的答案在大多数情况下也适用于您。) 长话大说:依赖于被调用的地方,魔术地表现不同的代码几乎总是一个坏主意。这会使必须维护您代码的人感到困惑,并且严重损害了您的

    • 我有一个如下所示的构造函数。 使用Mockito,我无法初始化所有3个对象accountDetailsRestClient、constantMapService和calculationMap。如果accountDetailsRestClient不为null,则constantMapService为null,反之亦然。 Mockito测试类: 但是accountDetailsRestClient现在

    • 问题内容: 我通过()存储了一个类列表,想实例化一个吗?这可能吗? 在我追求的方法看来,但它不支持构造函数? 问题答案: 您不能以这种方式构造新的类。 如果您具有类的名称,则可以使用Class.forName(className)加载/引用一个类。 如果您有要创建的类的字节码,则可以让类加载器加载字节码并为您提供该类。这可能比您预期的要先进。

    • 映射对构造函数没有限制或要求 (__init__ )类的方法。您可以自由地为您想要的函数要求任何参数,为ORM未知的实例分配属性,并且通常在编写Python类的构造函数时做您通常会做的任何其他事情。 sqlAlchemy ORM不调用 __init__ 从数据库行重新创建对象时。ORM的过程有点类似于Python标准库的 pickle 模块,调用低级 __new__ 方法,然后在实例上悄悄地恢复属

    • 生成类对象时,其成员可以用类的构造函数初始化。构造函数是与类同名的成员函数。程序员提供的构造函数在每次生成类对象(实例化)时自动调用。构造函数可以重载.提供初始化类对象的不同方法。数据成员应在类的构造函数中初始化或在生成对象之后设置其数值。 常见编程错误 6.7 类的数据成员只能在类定义中初始化。 常见编程错误 6.8 试图声明构造函数的返回类型和返回植是个语法错误。 编程技巧 6.5 适当时候(

    • 问题内容: Java 构造函数的文档说明: 注意:很少适合使用此构造函数。除非需要新实例,否则静态工厂通常是更好的选择。它可能会产生明显更好的时空性能。 如果是这样,为什么这个构造函数是公开的而不被弃用?是否有充分的理由使用此构造函数代替? 问题答案: Java 1.4中仅添加了它,因此似乎存在构造函数是为了向后兼容。 此票证解释了不弃用构造函数的原因: 由于该中断,API可能不推荐使用,因此,当