2017-06-20 72 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對於修改實體的狀態非常好。 –