一文解决 PHP静态(局部/全局)变量、auto(局部/全局)变量、类中static

一、静态局部变量、auto局部变量、类中static

这是我的概念:

类属性,类方法:是给类使用的,在类中使用 self::和 static:: 代表,供调用

实例属性,实例方法:是给实例使用的,在类中使用 this-> 代表,供调用

<?php
/**
 * User: X.W.X
 * Date: 2018-09-14
 * Time: 13:57
 * FileName: test.php
 * Introduce:
 */

// 当前 php7.0版本 好像还没有 静态函数,静态类的概念,所以 不测试
// 以下是主要测试内容:
// 测试 静态局部变量和auto局部变量 的区别
// 测试 类中 静态属性和非静态属性 的区别
// 测试 类中 静态方法和非静态方法 的区别
class TestStatic{

    // 类中有写static的属性和方法 ==> 类属性和类方法
    // 类中没写static的属性和方法 ==> 实例属性和实例方法

    // 有static ==> 类属性
    // 可使用 self::或者static:: 调用 ==> 二者的区别:  self:: 和 static:: 都代表者类,但self::始终代表当前类,而static:: 代表最后一次被重写的类
    public static $echo_static;
    // 无static ==> 实例属性
    // 可使用 $this-> 调用
    public $echo_auto;
    protected $echo_protected;

    // 实例方法 ==> 测试(普通变量=auto变量)
    public function test_auto(){
        // auto变量必须初始化 ==> 出函数之后,会被删除回收 ==> 再次进入函数,继续被初始化
        $i = 0;
        $this->echo_auto = $this->echo_auto.strval($i).',';
        $i++;
    }

    // 静态方法(类方法) ==> 测试(静态变量=static变量)
    public static function test_static() {
        // 只初始化一次 ==> 出函数之后,会被记住不回收,但其作用范围被局限在函数内,因此跟全局变量有所区别 
        // ==> 再次进入函数,不会被初始化,会从记住的值继续开始
        static $i;
        self::$echo_static = self::$echo_static.strval($i).',';
        $i++;
    }

    public function common()
    {
        foreach (range(0, 10) as $index) {
            // 展示 实例调用
            $this->test_auto();
            // 展示 静态调用
            static::test_static();
        }
    }


    public function testInstanceInherit(){
        // get_called_class() 获得当前调用类名
        $class = get_called_class();
        echo '当前类名: '.$class." 测试 公开实例方法 重写".PHP_EOL;
    }

    public static function testClassInherit(){
        $class = get_called_class();
        echo '当前类名: '.$class." 测试 公开类方法 重写".PHP_EOL;
    }

}

// 生成实例
$test = new TestStatic();
// 测试 static变量和auto变量
$test->common();
// 测试 实例调用实例方法,注意:不使用$符号
echo $test->echo_auto.PHP_EOL;
//echo $test->echo_static.PHP_EOL; // 实例调用类属性 报错,Accessing static property
// 测试 类调用类方法,注意:使用$符号,为什么呢?这是我的愚见:无实例化,那些类属性没被创建,因此使用$符号
echo TestStatic::$echo_static.PHP_EOL;
//echo TestStatic::$echo_auto.PHP_EOL; // 类调用实例属性 报错,Access to undeclared static property
/*
result:
    0,0,0,0,0,0,0,0,0,0,0,
     ,1,2,3,4,5,6,7,8,9,10,
*/

/**
 * 从以上结果可看出,php7.0版本
 * auto变量必须初始化 ==> 出函数之后,会被删除回收 ==> 再次进入函数,继续被初始化
 * static变量非必须初始化,默认初始化为null且只初始化一次 
 * ==> 出函数之后,会被记住不回收,但其作用范围被局限在函数内,因此跟全局变量有所区别 
 * ==> 再次进入函数,不会被初始化,会从记住的值继续开始
 */

class TestStaticSub extends TestStatic
{
    public function testInstanceInherit(){
        $class = get_called_class();
        echo '当前类名: '.$class." 测试 公开实例方法 重写".PHP_EOL;
        echo '当前类名: '.$class." 这是 重写内容".PHP_EOL;
    }

    public static function testClassInherit(){
        $class = get_called_class();
        echo '当前类名: '.$class." 测试 公开类方法 重写".PHP_EOL;
        echo '当前类名: '.$class." 这是 重写内容".PHP_EOL;
    }
}

// 父类TestStatic 实例
$test_static = new TestStatic();
// 子类TestStaticSub 实例
$test_static_sub = new TestStaticSub();

// 父类实例 调用父类实例方法
$test_static->testInstanceInherit();
// 父类实例 调用父类类方法
$test_static->testClassInherit();
// 子类实例 被重写,调用子类实例方法,==> 被重写规则:方法名和参数要都一样才会被重写
$test_static_sub->testInstanceInherit();
// 子类实例 被重写,调用子类类方法
$test_static_sub->testClassInherit();

echo PHP_EOL;
// 父类 调用 父类类方法
TestStatic::testClassInherit();
//TestStatic::testInstanceInherit(); // 父类 调用 父类实例方法 报错,Non-static method
// 子类 调用 子类方法
TestStaticSub::testClassInherit();
//TestStaticSub::testInstanceInherit(); // 子类 调用 子类实例方法 报错,Non-static method
// 从下面 结果 可看出 不管是类方法还是实例方法,只要方法名和参数相同,都会被重写 形成类多态
// 那有 类多态 有没有 实例多态呢?
/*
result:
    当前类名: TestStatic 测试 公开实例方法 重写
    当前类名: TestStatic 测试 公开类方法 重写
    当前类名: TestStaticSub 测试 公开实例方法 重写
    当前类名: TestStaticSub 这是 重写内容
    当前类名: TestStaticSub 测试 公开类方法 重写
    当前类名: TestStaticSub 这是 重写内容

    当前类名: TestStatic 测试 公开类方法 重写
    当前类名: TestStaticSub 测试 公开类方法 重写
    当前类名: TestStaticSub 这是 重写内容
*/

/**
 * 从以上结果可看出,php7.0版本
 * 1. 类方法会被实例所继承,但类属性暂时在当前版本是没被实例所继承,不像python3语言,实例默认继承类中的类属性和类方法
 * 2. 也就是说,当前PHP版本中 ==> 实例是调用不了类属性,但可调用类方法、实例属性、实例方法
 * 3. 若父类和子类中 名字和参数同时相同的,会被子类重写,反而反之,
 */

结语:

类中static==>类属性,供类使用

类中非static==>实例属性,供实例使用

注意:实例中的属性和方法 不会像Pyhon语言那样 都默认把类中的属性和方法 给继承了,PHP7.0默认继承只有方法,属性要不要继承自己开发

二、静态全局变量、auto全局变量

// test1.php
const a = '常量被导入';
$a = '普通全局变量被导入';
static $b = '静态全局变量被导入';
global $c;
$c = 'global全局变量被导入';
// 此为 test.php文件
// 测试 静态全局变量和auto全局变量
include_once 'test1.php';
// 网上说:静态全局变量,被局限于那个文件内,但我不管咋测试都是被导入
print_r(a.PHP_EOL);
print_r($a.PHP_EOL);
print_r($b.PHP_EOL);
print_r($c);
/*
result:
    常量被导入
    普通全局变量被导入
    静态全局变量被导入
    global全局变量被导入
*/

结语:

网上说的不一定是真的,需要自己验证

三、static::、self::的区别

class A
{
    public static function who() {
        echo __CLASS__;
    }
    public static function test() {
        self::who(); //AAA
//        static::who(); //ABB
    }
}
A::test();

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

class C extends B
{

}
C::test();
/**
 * 若无重写类属性或类方法:
 *    self和static的指向是一样的
 * 若有重写:
 *     self ==> 指向当前类,类似于直接使用类名 那为什么不使用直接类名而使用self?图省力
 *     static ==> 指向最后一次重写的类,后期绑定
 */

猜你喜欢

转载自blog.csdn.net/xwx_100/article/details/82381421