有时我会在别人的编码中看到这个...
$object->Something_1->Something_2;
我理解指向和反对函数或变量......
$object->Something_1;
$object->Something_1();
但我不明白串联的多个对象指针是如何工作的。我无法在网上找到任何解释这一点,所以也许我的搜索条款是错误的,但有人会解释或指向一篇我可以学习的文章吗?
我不知道实现这种用法需要什么,并且想知道我的编码是否可以从中受益。
答案 0 :(得分:3)
此:
$object->Something_1->Something_2();
几乎与此相同:
$temp = $object->Something_1;
$temp->Something_2();
所有这意味着Something_1
本身就是一个也有成员的对象,在本例中是方法Something_2
。语法没有什么特别之处。解析为对象的任何内容都可以使用->
调用其成员。所以$object
解析为一个对象,在这种情况下$object->Something_1
也是如此。
答案 1 :(得分:3)
您的原始代码示例可以重写为:$invoice->sender->getName();
在此代码中,变量$sender
已定义为public
(在类中,用于实例化$invoice
对象)。这意味着对象的封装被破坏了。代码还期望$sender
实际上包含一个对象。
您可以使用getter而不是直接访问变量来改进封装:$invoice->getSender()->getName();
但这种方法也被认为是code smell。它还会使调试非常烦人,并且经常导致违反Law of Demeter。
这种链接被认为是一种不好的做法。我强烈建议避免它。
唯一的例外是,当使用域实体时,常见的是设置器的链接。在这种情况下,看到这样的代码是很常见的:
$invoice
->setSender('John Doe')
->setReceivedOn(time())
->setOrder($data);
要实现它,方法将被定义如下:
public function setSender($sender) {
$this->sender = $sender;
return $this;
}
这个特殊的用例并不像其他用例那么糟糕,因为该类实际上并没有在->
链的链接之间进行更改(这使得前两个示例的调试成为一场噩梦)。但是我个人仍然会避免这种方法,因为 setters 不应该返回任何内容而 getters 不应该改变对象的状态。
TL; DR :不采用这种代码。
答案 2 :(得分:1)
基本上,当一个对象将一个或多个其他对象存储为属性时会发生这种情况。
例如:
class Car
{
public string $name;
public Engine $engine;
}
class Engine
{
public $someProp;
}
如果您在变量中有汽车,您可以像这样访问引擎的属性:
$car->engine->someProp;
(假设汽车已初始化,汽车发动机也是如此)