• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

PHP中的static

php 搞代码 3年前 (2022-03-01) 33次浏览 已收录 0个评论
文章目录[隐藏]

PHP中的static

对于动态变量和办法的问题也是面试中常常会呈现的问题,这种问题多看手册搞明确原委就能解决,只是的确对于动态变量的问题还是比拟绕的,这里咱们就联合手册用理论的代码来看!

<code class="php">
class Test
{
    static $v = 'a';

    static function showV()
    {
        echo self::$v;
    }

    function showVV()
    {
        echo self::$v;
    }

    static function showVVV()
    {
        // $this->showVV(); // 会间接报错
    }
}

先筹备一个类,这外面有动态变量、静态方法,其中showV()办法是静态方法调用动态变量,showVV()办法是一般办法调用动态变量,showVVV()办法是一般办法调用静态方法。

从正文中能够看出第一个问题,一般办法应用$this调用静态方法会报错,也就是说,$this这个东东对于所有动态的货色都是不敌对的,不信您关上正文试试,也能够去调用动态的$v变量,间接就是语法错误的提醒。

接下来,咱们实例化类,并开始一些测试

<code class="php">$t = new Test();
$t->showV();
//echo $t->v; // 报异样
echo Test::$v;
//Test::showVV(); // 报异样
$t->showVV();
  • 1行:实例化的类间接调用showV(),这是没问题的,静态方法能够通过一般的形式调用,当然咱们正规的应该是应用Test::showV()来进行调用,留神这里面试的时候会是坑
  • 2行:失常调用
  • 2行:间接->v是不行的,办法能够进行一般调用,但属性不行
  • 3行:用动态调用的形式是没问题的
  • 4行:失常获取动态变量
  • 5行: 应用::当然不能调用非静态方法啦
  • 6行:失常办法中能够应用动态变量

那么问题来了,静态方法中不能应用$this,如何取得变量内容呢?请参考单例模式,未来咱们会在设计模式的系列文章中讲到,这里先卖个关子,大家也能够本人钻研下。

下面是失常来说一些比较简单的动态属性和办法的演示,接下来好玩的货色就来了。

初始化个性

<code class="php">class Calculate
{
    function cacl()
    {
        static $a = 1;
        echo $a;
        $a++;
    }

    static function cacl2()
    {
        static $a = 1;
        echo $a;
        $a++;
    }

    static $b = 1;

    static function cacl3()
    {
        echo self::$b;
        self::$b++;
    }
}

$calculate = new Calculate();
$calculate->cacl(); // 1
$calculate->cacl(); // 2

Calculate::cacl2(); // 1
Calculate::cacl2(); // 2

Calculate::cacl3(); // 1
Calculate::cacl3(); // 2

看着代码很多,其实都是在讲一件事儿,如果是一般的$a和$b,那么每次都在从新赋值,echo进去的都是0,然而动态属性可不一样。动态属性是运行时计算的,只在第一次赋值的时候是真正的赋值操作,而后并不会进行赋值,能够相当于这一行代码不存在。

动态变量只在部分的作用域中存在,来到这个作用域也不会失落,当然也不能再次初始化。学过前端的同学肯定会拍案而起,这不是闭包的作用域嘛??的确很像,而且用途也十分像,比方咱们做一个递归:

<code class="php">function test1()
{
    static $count = 0;

    $count++;
    echo $count;
    if ($count < 10) {
        test();
    }
    $count--;
}

test1();

在不理解static之前,完结递归咱们可能须要给办法传递一个数字进来,但当初仿佛是不须要了,应用外部的动态变量就能够解决了。

援用对象问题

<code class="php">
class Foo
{
    public $a = 1;
}

function getRefObj($o)
{
    static $obj;
    var_dump($obj);
    if (!isset($obj)) {
        $obj = &$o;
    }
    $obj->a++;
    return $obj;
}

function getNoRefObj($o)
{
    static $obj;
    var_dump($obj);
    if (!isset($obj)) {
        $obj = $o;
    }
    $obj->a++;
    return $obj;
}

$o    = new Foo;
$obj1 = getRefObj($o); // NULL
$obj2 = getRefObj($o); // NULL

$obj3 = getNoRefObj($o); // NULL
$obj4 = getNoRefObj($o); // Foo

又是一大串代码,啥也不说,先复制下来运行一下看看后果是不是一样。在应用援用对象时,咱们赋值的是内存援用地址。然而同样的起因,动态属性是运行时产生的,而援用地址不是动态地存储,于是,赋不上值了呗,永远会是NULL。不信你接着用getRefObj()再生成几个试试。理论利用中反正要记住,这种状况下千万不要把援用值赋给动态变量就行了,而下面起因的了解的确还是比拟绕的,能讲明确最好,讲不明确就记住这个事儿。

前期动态绑定

<code class="php">
class A
{
    static function who()
    {
        echo __CLASS__ . "\n";
    }

    static function test()
    {
        self::who();
    }
}

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

B::test(); // A

先看这一段,应用self输入的后果会是A,但如果应用一般的类实例化,并且应用一般办法的话,输入的会是B,大家能够尝试下。起因呢,就是self是取决于以后定义方法所在的类。这就是动态属性办法的另一大特点,不实例化,跟随着类而不是实例。

class A{…},这个货色叫做类,是对事实的形象,咱们能够了解为一个模板,这外面的货色是假的,没有生命的。$a = new A了之后,这个$a才是对象,相当于是复制一了个模板做了一个真的货色进去,是有生命的。就如同咱们做一个锤子,须要一个模具,这玩意就是类,而后浇铸金属后成型拿进去,这玩意就是对象。一个对象有真正的内存地址空间的。

非动态的属性和办法是在对象中的,是咱们浇进去的金属。也就是new了之后才有的货色,而动态属性和办法是依附于class A的,是运行时进行编译读取的。

当初咱们回过头来看最早的例子,一般办法中调用静态方法或变量,实际上就是在这个实例化对象中调用了Test::showV(),只是咱们应用了self关键字而已。仍然是走的动态过程而不是这个对象中真的蕴含了showV()这个办法,因而,$this当然取不到啦!

那么,如何让父类A中test()办法去调用到子类的who()办法呢?

<code class="php">
class AA
{
    static function who()
    {
        echo __CLASS__ . "\n";
    }

    static function test()
    {
        static::who();
    }
}

class BB extends AA
{
    static function who()
    {
        echo __CLASS__ . "\n";
    }
}

BB::test(); // BB

没错,应用static::关键字这种模式调用,static示意运行最后时的类,不是办法定义时的类。这样就实现了前期动态绑定。另外,parent::和self::是会转发这个链条的。

<code class="php">
class AAA
{
    public static function foo()
    {
        static::who();
    }

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

class BBB extends AAA
{
    public static function test()
    {
        AAA::foo();
        parent::foo();
        self::foo();
    }

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

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

CCC::test(); // AAA、CCC、CCC
  • CCC继承了BBB,BBB继承了AAA
  • 在AAA中的foo()办法应用了static::who()来调用who()办法
  • BBB中的test()执行了三种调用
  • 后果是parent::foo()和self::foo()都将CCC传递了过来,最初应用的是CCC的who()办法

这个例子看着很绕,但其实论断就一个,如果父类应用了static关键字来调用父子类都有的内容,那么就是以哪个子类在里面进行调用了为准,就像一般类的办法调用 一样。反过来,self就是以这个self关键字所在的类为准。

说了这么多,也算是把static动态的个性解说的差不多了。在理论利用中还是要综合思考,不能因为动态属性不便就全都应用动态属性和办法或者齐全不应用,还是要联合各路业务需要进行取舍。

具体代码:
https://github.com/zhangyue0503/php/blob/master/newblog/php-static.php


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:PHP中的static

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址