2017-06-20 35 views
-1

有时我看到这个人编码...PHP中多“引用”(对象指针)的上下文是什么?

$object->Something_1->Something_2; 

我明白指向和目标函数或变量,如...

$object->Something_1; 
$object->Something_1(); 

但我不明白是怎么多对象指针串在一起工作。我一直无法在网上找到任何解释,所以也许我的搜索条件是错误的,但有人会解释或指向我的文章,我可以学习这一点?

我不知道实现这样的用法需要什么,并希望看看它是否可以从我的编码中受益。

+2

'$ object-> Something_1'的值本身就是一个对象。没有更多,没有更多。与$ array ['foo'] ['bar']''不同,它是数组中的数组。 – deceze

回答

3

此:

$object->Something_1->Something_2(); 

是几乎相同的,因为这:

$temp = $object->Something_1; 
$temp->Something_2(); 

所有它的意思是Something_1是本身也具有成员的对象,在这种情况下该方法Something_2。语法没有什么特别之处。任何解析为对象的成员都可以使用->调用其成员。因此,$object解析为一个对象,在这种情况下,$object->Something_1也是如此。 $invoice->sender->getName();

在此代码可变$sender已被定义为public(在类,这是用于实例化对象$invoice):

+0

谢谢!欣赏它。我给你的答案是因为这是最简单的解释。我还做了一个小代码示例,我认为它基于你告诉我的内容很容易理解。如果你喜欢,也许你可以添加到你的答案或类似的东西。无论哪种方式,谢谢! @ https://gist.github.com/NoahjChampion/87bc9271dd8c05d110032c05730c962a –

1

基本上,这发生在一个对象存储一个或多个其他对象作为属性时。

例如:

class Car 
{ 
    public string $name; 
    public Engine $engine; 
} 
class Engine 
{ 
    public $someProp; 
} 

,如果你有一个可变的汽车,你可以进入内燃机的性能像这样:

$car->engine->someProp; 

(假设汽车被初始化等在汽车发动机)

+0

嗨。你可以在类似的字符串中声明类的引用吗?像公共Class_Name一样?我试着用你的代码,并得到意外的字符串错误。以为我明白你的意思,想知道是否有一种简单的方法来做这样的事情。在类级别而不是类级别上声明一个类。 –

+0

@NoahjChampion哦,数据类型只适用于PHP 7+,如果你使用的是旧版本,你可以删除数据类型(字符串和引擎),他们主要是在那里来说明反正 – FMashiro

3

你的原代码样品可以作为被重写。这意味着对象的封装被破坏。代码还预计,$sender实际上将包含一个对象。

你可以提高封装,通过使用一个getter,而不是直接访问变量:$invoice->getSender()->getName();

但这种方法也被认为是一个code smell。这也会使调试非常烦人,并且经常导致违反Law of Demeter

这样的链接被认为是不好的做法。我强烈建议避免它。

唯一的例外是常见的setter链接,当使用域实体时。在这种情况下,这将是我们经常见到这样的代码:

$invoice 
    ->setSender('John Doe') 
    ->setReceivedOn(time()) 
    ->setOrder($data); 

为了实现它,这些方法很有点像这样定义:

public function setSender($sender) { 
    $this->sender = $sender; 
    return $this; 
} 

这种特殊的用例是不一样糟糕其他人,因为这个班级实际上并没有改变链接的链接(这使前两个例子的调试变成了一场噩梦)。但我个人仍然会避免这种做法,因为设置器不应该返回任何东西,并且获取器不应该更改对象的状态。

TL; DR:不采用这种风格的代码。

+0

我总是在构造或初始化时使用Singleton,而不是你在这里提到的'setSender'方法。我认为调试它比'setSender'方法更容易。 – ICE

+0

另一件事,你可以使用'return($ this-> sender instanceof SENDER)? true:false;'而不是'返回$ this;'用于'setSender'方法。这样做更有意义。 – ICE

+1

@ICE恕我直言,最好的方法是不要从* setters *返回,坚持[** CQS **](https://www.martinfowler.com/bliki/CommandQuerySeparation.html)。至于单身人士 - 他们被认为是反模式(观看[this](https://www.youtube.com/watch?v=-FRm3VPhseI)了解原因)。至于在构造函数中传递依赖关系 - 我个人更喜欢只使用构造函数来注入**强制**依赖项,除非您使用[DDD](https://www.goodreads.com/book/show/179133)。 Domain_Driven_Design),setter对于修改实体的状态非常好。 –