DanceSmile / dancesmile.github.io

dancesemile's github pages
4 stars 1 forks source link

后期静态绑定 #10

Open DanceSmile opened 6 years ago

DanceSmile commented 6 years ago

该功能从语言内部角度考虑被命名为“后期静态绑定”。“后期绑定”的意思是说,static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。也可以称之为“静态绑定”,因为它可以用于(但不限于)静态方法的调用。

static:: 简单用法

class A {
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        static::who(); // 后期静态绑定从这里开始
    }
}

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

B::test();

非静态环境下使用 static

class A {
    private function foo() {
        echo "success!\n";
    }
    public function test() {
        $this->foo();
        static::foo();
    }
}

class B extends A {
   /* foo() will be copied to B, hence its scope will still be A and
    * the call be successful */
}

class C extends A {
    private function foo() {
        /* original method is replaced; the scope of the new one is C */
    }
}

$b = new B();
$b->test();
$c = new C();
$c->test();   //fails

转发和非转发调用

class A {
    public static function foo() {
        static::who();
    }

    public static function who() {
        echo __CLASS__."\n";
    }
}

class B extends A {
    public static function test() {
        A::foo();
        parent::foo();
        self::foo();
    }

    public static function who() {
        echo __CLASS__."\n";
    }
}
class C extends B {
    public static function who() {
        echo __CLASS__."\n";
    }
}

C::test();

应用案列

获取数据库名称


class Model 
{ 
    public static function getName() 
    { 
        echo static::$name; 
    } 
} 

class Product extends Model 
{ 
    protected static $name = 'Product'; 
} 

class User extends Model 
{ 
    protected static $name = 'User'; 
} 

Product::getName(); 
User::getName(); 

通过超类创建实例对象

abstract class A{

    static function create(){

        //return new self();  //Fatal error: Cannot instantiate abstract class A

        return new static(); //this is the correct way

    }

}

class B extends A{
}

$obj=B::create();
var_dump($obj);
static::class and self::class can be used to get current class name, 
work under 5.5 and 5.6
failed in 5.3.

<?php
class a{ 
    function d() {
        echo "=== self::class ===\n";
        var_dump(self::class);
        echo "=== static::class ===\n";
        var_dump(static::class);
    }
}
class b extends a{}
class c extends b{}

a::d(); 
b::d();
c::d();

/*
Output: 

=== self::class ===
string(1) "a"
=== static::class ===
string(1) "a"
=== self::class ===
string(1) "a"
=== static::class ===
string(1) "b"
=== self::class ===
string(1) "a"
=== static::class ===
string(1) "c"

*/

    class Singleton {

        public static $objInstance;

        public static function &getInstance() {
            if (self::$objInstance == null) {
                $strClass = static::getClass();
                self::$objInstance = new $strClass;
            }
            return self::$objInstance;
        }

        public static function getClass() {
            return __CLASS__;
        }

    }

    class Foo extends Singleton {

        public $intBar;

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

        public static function getClass() {
            return __CLASS__;
        }

    }

    $objFooTwo = Foo::getInstance();
    $objFooTwo->intBar = 2;

    $objFooOne = Foo::getInstance();

    if ($objFooOne->intBar == $objFooTwo->intBar) {
        echo 'it is a singleton';
    } else {
        echo 'it is not a singleton';
    }