可以从现有对象实例化吗? [英] Acceptable to instantiate from an existing object?

查看:60
本文介绍了可以从现有对象实例化吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我偶然发现了这一点,并想知道这是否是预期的行为:

I discovered this by accident, and was wondering if this is expected behaviour:

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;

My question is about the line, $taffy = new $puppy;

通常,我会编码 $taffy = new dog;

我不希望能够通过从实例化实例化来创建新对象......如果这有意义的话.

I wouldn't have expected to be able to create a new object by instantiating from an instantiation... if that makes any sense.

这是预期的功能,还是只是一个意外?

Is this expected functionality, or just a happy accident?

我在构建需要与多个不同数据库表对话的模型时发现了这一点,我使用依赖注入来传递数据库抽象:

I discovered this when building a model that needed to talk to several different db tables, and I use dependency injection to pass the database abstraction:

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 行的获取.那么是否可以接受

Sometimes, though, a database call to ModelTwo in the middle of a loop fetching ModelOne's rows could clobber the fetching of ModelOne's rows. So is it acceptable to

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

推荐答案

我从未见过或做过.因此,我可能会避免它:如果它会导致其他开发人员看到它并挠头(就像你一样),它可能不值得.毕竟,我看不出有什么理由让你特地这样做.

I've never seen this or done this. As a result, I would probably avoid it: if it is going to cause other developers to look at it and scratch their heads (just like you did), it probably isn't worth it. I can't see any reason why you would specifically have to do this, after all.

Don't Panic 指出,虽然没有明确记录,但在 PHP 文档中有一个这样做的例子.本页示例 5.

Don't Panic has pointed out that, while not explicitly documented, there is an example of doing this in the PHP documentation. Example 5 on this page.

话虽如此,但没有进行克隆:

That being said, there is no cloning going on:

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.这似乎是以下内容的有效简写:

If you do the above you will find that the objects are not the same and the __clone method is never called. Also, your taffy will be initialized with the name of doggy, not Puppy. It seems this is effectively shorthand for:

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

这篇关于可以从现有对象实例化吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆