【问题标题】:Why return a clone of an object in oop?为什么要在 oop 中返回对象的克隆?
【发布时间】:2018-03-01 10:10:39
【问题描述】:

我最近不得不使用Slim\Http\MessageSlim\Http\Request 来获取用户发布的数据。

我注意到 withBody() 方法中的某些内容返回对象的克隆而不是 $this

这给我带来了一些麻烦,因为在我将 $request->withBody(...) 分配给一个变量 ($request) 并在我的脚本中继续使用该新变量之前,我无法让我的应用程序工作。

我有一个模拟示例来解释(见代码中的 cmets);

class Request {
    protected $body;

    public function addBody($body) {
        $clone = clone $this;
        $clone->body = $body;
        return $clone;
    }

    public function getBody() {
        return $this->body;
    }
}

$request = new Request;

// this will return NULL
$request->addBody([
    'name' => 'john',
    'email' => 'john@example.com',
]);

var_dump($request->getBody());

// -----------------------

// but this will return the "body" that was passed in above.
$request = $request->addBody([
    'name' => 'john',
    'email' => 'john@example.com',
]);

var_dump($request->getBody());

我明白这里发生了什么。但我不明白为什么一个类会这样实现。

有什么好处?为什么要这样限制开发者?

【问题讨论】:

标签: php oop clone slim


【解决方案1】:

Slim 使用 PSR-7 HTTP 消息接口标准,其自身描述如下:

<?php
namespace Psr\Http\Message;

/**
 * HTTP messages consist of requests from a client to a server and responses
 * from a server to a client. This interface defines the methods common to
 * each.
 *
 * Messages are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 *
 * @see http://www.ietf.org/rfc/rfc7230.txt
 * @see http://www.ietf.org/rfc/rfc7231.txt
 */
interface MessageInterface
{
    //etc
}

“消息被认为是不可变的”。它们被认为是值对象,它永远不能改变状态,如果你确实想改变状态,就会返回一个新的实例。

这是一个解释值对象的链接http://deviq.com/value-object/

还有我链接的页面的一些摘录:

值对象是一种不可变类型,只能通过以下方式区分 其属性的状态。也就是说,与实体不同,实体具有 唯一标识符,即使其属性是 否则相同,两个具有完全相同属性的值对象 可以认为是平等的。值对象是首先描述的模式 在 Evans 的领域驱动设计书中,并在 Smith 中进一步解释 和 Lerman 的领域驱动设计基础课程。

希望这能帮助您理解原因!

最后,在这里http://www.php-fig.org/psr/psr-7/看看实际的 PSR-7 标准

【讨论】:

  • 问题是什么是好处以及为什么它限制使用如此复杂。你对此一无所知。
【解决方案2】:

我也想问同样的问题……

我在这个设计中发现的唯一好处是你可以像PSR-7 HttpClients this..一样将一些方法调用链接在一起。

$request = $request
  ->withBody($body)
  ->withHeader('Content-Lenght', strlen($body))
  ->withHeader('Content-Type', 'text/plain')
  ->withHeader('User-Agent', 'xxxx');

但在我看来,小小的好处不值得接受它的所有负面影响。 例如。使用此设计为每个方法调用创建对象的副本。 当您拥有大数据对象或有许多方法调用时,这意味着大量内存浪费。

【讨论】:

    猜你喜欢
    • 2018-01-05
    • 2012-04-21
    • 2015-03-02
    • 2021-04-29
    • 2011-01-09
    • 2017-06-06
    • 1970-01-01
    • 2015-06-23
    • 1970-01-01
    相关资源
    最近更新 更多