2017-08-25 5 views
2

私は事故によってこれを発見し、これは予期される動作であればと思いまして:既存のオブジェクトからインスタンス化することは可能ですか?

Interactive shell 

php > class dog { 
php { public $name='doggy'; 
php { public function speak() { 
php {  echo "bark, bark! (my name is " . $this->name . ")\n"; 
php { } 
php { } 
php > 
php > $puppy = new dog; 
php > $puppy->speak(); 
bark, bark! (my name is doggy) 
php > 
php > $taffy = new $puppy; 
php > $taffy->speak(); 
bark, bark! (my name is doggy) 
php > 
php > $taffy->name = "Taffy"; 
php > $taffy->speak(); 
bark, bark! (my name is Taffy) 
php > 
php > $puppy->speak(); 
bark, bark! (my name is doggy) 
php > 

私の質問は、ライン、$taffy = new $puppy;

通常約、私は$taffy = new dog;

をコード化しているだろうされて、私は「wouldnインスタンス化からインスタンス化することによって新しいオブジェクトを作成できると期待しています...もしそれが意味をなさないならば。

この機能は期待されていますか?


いくつかの異なるDBテーブルに話をするために必要なモデルを構築するとき、私はこれを発見し、私は、データベースの抽象化を渡すために、依存性注入を使用します。

class ShowConnectedTables { 
    public function __constructor($db) { 
    $this->modelOne = new ModelOne($db); 
    $this->modelTwo = new ModelTwo($db); 
    } 
    // ... snip ... 
} 

$table = new ShowConnectedTables(new Database); 

しかし場合によっては、へのデータベース呼び出しをModelOneの行をフェッチするループの途中にあるModelTwoは、ModelOneの行のフェッチを壊す可能性があります。だからそれは許容可能です

class ShowConnectedTables { 
    public function __constructor($db) { 
    $this->modelOne = new ModelOne($db); 
    $this->modelTwo = new ModelTwo(new $db); // note new abstraction 
    } 
    // ... snip ... 
} 

$table = new ShowConnectedTables(new Database); 
+0

それは確かに 'clone'を使用するのがより一般的です - 私はそれが状態をしたいのではなく、既存のものに基づいて新しいオブジェクトを作成することが特に一般的な状況だとは思わないコピーに代理すること。私はこれもうまくいきませんでした(そして、PHP 5が最初に出て以来のことです)。何かを教えてくれてありがとう。 – iainn

+0

ここを参照してください:http://php.net/manual/language.oop5.basic.php#example-218明らかに、この動作は非従来的ではありません。この例では、@MarkBakerは間違っているように見えます。 – Kaddath

+1

@ MarkBaker私はそれが '$ newObj = * new * $ existingObj'ではなく' $ newObj = $ existingObj'を実行することを指していると思います。 – iainn

答えて

2

私はこれを見たことがないかこれを行った。結果として、私はおそらくそれを避けるでしょう:他の開発者にそれを見て頭を傷つけるようにするなら(おそらくそうであったように)、おそらくそれは価値がありません。結局のところ、これをやる必要がある理由はわかりません。

Do not Panicは、明示的に文書化されていないが、PHPのドキュメントでこれを行う例があることを指摘しています。言われて、起こって何のクローニングが存在しないことExample 5 on this page.

class dog { 
    public $name='doggy'; 
    public function speak() { 
    echo "bark, bark! (my name is " . $this->name . ")\n<br>"; 
    } 
    public function __clone() { 
     print 'This is not called!'; 
     parent::__clone(); 
    } 
} 
$class = 'dog'; 
$puppy = new dog; 
$puppy->name = 'Puppy'; 
$taffy = new $puppy; 
if (spl_object_hash($taffy) != spl_object_hash($puppy)) 
    print 'not the same object'; 
$taffy->speak(); 

あなたがあなたの上に行う場合は、オブジェクトが同じではないと__cloneメソッドが呼び出されないことがわかります。また、あなたのタフィーはdoggyという名前ではなく、Puppyという名前で初期化されます。

$class = get_class($puppy); 
$taffy = new $class; 
+2

多少説明されています。 [http://php.net/manual/en/language.oop5.basic.php](here)、例5です。それについての説明はありません。 –

+0

ありがとう@ Don'tPanic!私は一致するように編集しました。 –

+0

もちろん、そこにはドキュメントがあります。しかし、見逃しやすい。 'get_class'は私がこれを見つけたときに試していたものでした。入力いただきありがとうございます。私は答えを受け入れる前にこれを1日放置しておきます。 –

1

これは、既存のオブジェクトへの新しい参照を作成する問題ではありません。コンストラクタが実行されるので、これは新しいオブジェクトです。

<?php 

class dog { 
    public $name; 
    public function __construct($name = '') { 
     $this->name = $name ?: 'doggy'; 
    } 
    public function speak() { 
    echo "bark, bark! (my name is " . $this->name . ")\n"; 
    } 
} 

$puppy = new dog; 
$puppy->speak(); #bark, bark! (my name is doggy) 

$taffy = new $puppy('Snuffels'); 
$taffy->speak(); #bark, bark! (my name is Snuffels) 

$taffy->name = "Taffy"; 
$taffy->speak(); #bark, bark! (my name is Taffy) 

$puppy->speak(); #bark, bark! (my name is doggy) 
echo $puppy; 

理由IMOが、あなたはすでに新しいオブジェクトを作成することが可能で、クラスのコンテキストでhttp://php.net/manual/en/language.oop5.basic.php

を参照してください、new selfまたはnew parentのようなものを使用することができます:私は疲れてきましたnew selfおよびnew parent

私は、彼らがnewの後のものからクラス認識を実装すると仮定します。しかし、まだ良いWTF :)

関連する問題