在PHP中实例化类的正确方法

时间:2014-07-09 12:00:17

标签: php instance instantiation

我正在尝试在类中创建一个方法,它将实例化当前所在的类。但我还需要使用此方法在所有扩展类中正常工作。正如我从this thread学到的,使用self关键字来完成此任务并不好。如此明显的选择是使用static关键字。

但是,我遇到了不同的方法也可以。

示例:

class SimpleClass
{
    private $arg;

    public function __construct( $arg ){
        $this->arg = $arg;
    }

    public function getArg(){return $this->arg;}
    public function setArg($arg){$this->arg = $arg;}

    public function staticInstance()
    {
        return new static( $this->arg );
    }

    public function thisInstance()
    {
        return new $this( $this->arg );
    }

    public function selfInstance()
    {
        return new self( $this->arg );
    }
}

class ExtendedClass extends SimpleClass
{
}

$c1 = 'SimpleClass';
$c2 = 'ExtendedClass';

$inst1 = new $c1('simple');
$inst2 = new $c2('extended');

$static_instance_1 = $inst1->staticInstance();
$this_instance_1 = $inst1->thisInstance();
$self_instance_1 = $inst1->selfInstance();

$static_instance_2 = $inst2->staticInstance();
$this_instance_2 = $inst2->thisInstance();
$self_instance_2 = $inst2->selfInstance();

echo "SimpleClass Instances\n";
echo get_class($static_instance_1);
echo get_class($this_instance_1);
echo get_class($self_instance_1);

echo "ExtendedClass Instances\n";
echo get_class($static_instance_2);
echo get_class($this_instance_2);
echo get_class($self_instance_2);

正如我在本例中所看到的,staticInstancethisInstance都会产生“正确”的结果。或者他们呢?

有人可以解释这两种方法之间的差异,以及哪种方法是“正确的”。

1 个答案:

答案 0 :(得分:1)

php.net说:

从PHP 5.3.0开始,PHP实现了一个名为late static bindings的功能,可用于在静态继承的上下文中引用被调用的类。

更准确地说,后期静态绑定通过存储在最后一次“非转发调用”中命名的类来工作。在静态方法调用的情况下,这是显式命名的类(通常是::运算符左侧的类);在非静态方法调用的情况下,它是对象的类。 “转发调用”是由self ::,parent ::,static ::引入的静态调用,或者,如果在类层次结构中上传,则为forward_static_call()。函数get_called_class()可用于检索具有被调用类名称的字符串,static ::引入其范围。

此功能被命名为“后期静态绑定”,并考虑了内部视角。 “后期绑定”来自于以下事实:static ::不会使用定义方法的类来解析,而是使用运行时信息来计算。它也被称为“静态绑定”,因为它可以用于(但不限于)静态方法调用。

自我限制:

对当前类的静态引用(如self ::或 CLASS )使用函数所属的类进行解析,如在其定义的位置:

<?php
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        self::who();
    }
}

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}

B::test();
?>

以上示例将输出:A

延迟静态绑定的用法:

后期静态绑定尝试通过引入引用最初在运行时调用的类的关键字来解决该限制。基本上,一个关键字允许您从前一个示例中的test()引用B.决定不引入新的关键字,而是使用已经保留的静态。

<?php
class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        static::who(); // Here comes Late Static Bindings
    }
}

class B extends A {
    public static function who() {
        echo __CLASS__;
    }
}

B::test();
?>

以上示例将输出:B

$this关键字是指当前对象,您不能在静态方法中使用它。当你说return $this时,它意味着某个方法返回调用它的同一个对象。

所以正确的方法是使用static关键字,因为如果你说return new static()它指的是该方法当前所在的类。