繁体   English   中英

可以从现有对象实例化吗?

[英]Acceptable to instantiate from an existing object?

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

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;编码$taffy = new dog;

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

这是预期的功能,还是不幸的事故?


我在构建需要与几个不同的数据库表进行通信的模型时发现了这一点,并且我使用依赖注入来传递数据库抽象:

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

我从未见过或做过此事。 结果,我可能会避免:如果这将导致其他开发人员看它并挠头(就像您所做的那样),则可能不值得。 毕竟,我看不出您为什么要专门这样做的任何原因。

不要恐慌指出,尽管没有明确记录,但PHP文档中有一个执行此操作的示例。 此页面上的示例5。

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

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;

这不是创建对现有对象的新引用的问题。 构造函数被执行,这意味着这是一个新对象。 我已经累了:

<?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的原因是,您已经可以使用诸如new selfnew parent类的东西,请参见http://php.net/manual/en/language.oop5.basic.php

在类上下文中,可以通过new selfnew parent创建一个新对象。

我假设,他们从new之后的事物中实现了类识别。 但是还是一个不错的WTF :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM