为什么在面向对象编程中要返回一个对象的克隆?

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

我在方法 withBody() 中注意到了一个问题,它返回对象的克隆而不是 $this

这给我带来了一些麻烦,因为我不能让我的应用程序正常工作,直到我将 $request->withBody(...) 分配给一个变量($request),然后在我的脚本中继续使用该新变量。

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

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());

我看到这里正在发生的事情。但我不明白为什么一个类会像这样实现。
有什么好处吗?为什么要以这种方式限制开发人员呢?

4
你可以去了解“不可变对象”(Immutable Objects)。参考链接:https://blog.joefallon.net/2015/08/immutable-objects-in-php/。 - Fildor
函数式编程 - nl-x
被投票关闭,因为基于个人观点。请尝试访问 https://softwareengineering.stackexchange.com 进行提问。我无法将其迁移至该网站。 - nl-x
1
这不是基于观点的,他想要理解不可变值对象的设计模式。 - delboy1978uk
2个回答

2

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的领域驱动设计基础课程中进一步解释。
希望这能帮助您理解原因!
最后,请看一下实际的PSR-7标准:http://www.php-fig.org/psr/psr-7/

问题是什么是好处,为什么它限制使用变得如此复杂。你没有回答任何一个问题。 - Radon8472

0
我想问同样的问题...
在这个设计中,我唯一发现的好处是你可以像PSR-7 HttpClients那样链接一些方法调用。
$request = $request
  ->withBody($body)
  ->withHeader('Content-Lenght', strlen($body))
  ->withHeader('Content-Type', 'text/plain')
  ->withHeader('User-Agent', 'xxxx');

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接