当前位置: 首页 > 后端技术 > PHP

PHP中的Static

时间:2023-03-29 13:58:40 PHP

关于静态变量和方法的问题也是面试中常见的问题。这类问题只要看说明书,了解原委就可以解决。但是,关于静态变量的问题还是比较迷惑。这里我们就结合手册看一下实际的代码吧!类测试{static$v='a';静态函数showV(){echoself::$v;}functionshowVV(){echoself::$v;}staticfunctionshowVVV(){//$this->showVV();//会直接报错}}首先准备一个类,里面包含静态变量和静态方法,其中showV()方法是调用静态变量的静态方法,showVV()方法是调用静态变量的普通方法,showVVV()方法是调用静态方法的普通方法。从评论中,我们可以看出第一个问题。普通方法使用$this调用静态方法会报错。可以调用static$v变量,直接是语法错误提示。接下来,我们实例化该类并开始一些测试$t=newTest();$t->showV();//echo$t->v;//报告异常echoTest::$v;//Test::showVV();//报告异常$t->showVV();第1行:实例化类直接调用showV(),没有问题。静态方法可以正常调用,当然我们正规的应该是用Test::showV()来调用。注意这里面试会有2行坑:2行正常调用:direct->v不行,方法可以正常调用,但是属性不能3行:静态调用的方法是no问题。第4行:正常获取静态变量。5行:Use::当然不能调用非静态方法。6行:可以在普通方法中使用静态变量。这个,如何获取变量内容?请参考单例模式,我们会在以后的设计模式系列文章中讲到,这里先说明一下,大家可以自己研究一下。以上就是一些比较简单的静态属性和方法的演示,接下来就是好玩的东西了。初始化属性classCalculate{functioncacl(){static$a=1;回声$a;$a++;}静态函数cacl2(){静态$a=1;回声$a;$a++;}静态$b=1;静态函数cacl3(){echoself::$b;自我::$b++;}}$calculate=newCalculate();$calculate->cacl();//1$计算->cacl();//2计算::cacl2();//1计算::cacl2();//2计算::cacl3();//1计算::cacl3();//2看一大堆代码,但都在讲一个东西儿子,如果是普通的$a和$b,那么每次都重新赋值,回显输出都是0,只是静态属性不一样.静态属性是在运行时计算的,只有第一次赋值才是真正的赋值操作,之后不会进行任何赋值,可以相当于这行代码不存在。静态变量只存在于局部作用域,离开这个作用域也不会丢失,当然也不能再次初始化。学过前端的同学肯定会喷起来,这不就是闭包的范围吗??真的很像,用处也很像。例如,我们做一个递归:functiontest1(){static$count=0;$计数++;回声$计数;如果($count<10){测试();}$count--;}test1();在我们知道static之前,我们可能需要给方法传递一个数字来结束递归,但是现在好像不需要了,可以使用内部static变量来解决。引用对象问题classFoo{public$a=1;}functiongetRefObj($o){static$obj;变量转储($obj);如果(!isset($obj)){$obj=&$o;}$obj->a++;返回$obj;}functiongetNoRefObj($o){static$obj;变量转储($obj);如果(!isset($obj)){$obj=$o;}$obj->a++;返回$obj;}$o=newFoo;$obj1=getRefObj($o);//NULL$obj2=getRefObj($o);//NULL$obj3=getNoRefObj($o);//NULL$obj4=getNoRefObj($o);//foo又是一大串代码,什么都不说,先复制过来运行一下,看看结果是不是一样。在使用引用对象时,我们分配的是内存引用地址。但同理,静态属性是在运行时生成的,引用地址不是静态存储的,所以不能赋值,永远为NULL。如果您不相信我,请使用getRefObj()生成更多并重试。在实际应用中,你应该记住,在这种情况下,你永远不应该将引用值赋给静态变量。以上原因的理解确实比较绕。最好能解释清楚。如果你不明白,只要记住这个儿子。后期静态绑定classA{staticfunctionwho(){echo__CLASS__."\n";}静态函数测试(){self::who();}}B类扩展A{静态函数who(){echo__CLASS__。"\n";}}B::测试();//A先看这一段,使用self的输出结果会是A,但是如果使用普通的类实例化,使用普通的方法,输出的结果就是B,大家可以试试。原因是self依赖于当前定义的方法所在的类。这是静态属性方法的另一大特点,不实例化,跟随类而不是实例。classA{...},这个东西叫做类,是对现实的抽象。我们可以把它理解为一个模板,里面的东西都是假的,没有生命的。$a=newA之后,这个$a就是对象,相当于复制了一个模板,做了一个真实的东西,是活的。就好像我们做了一把锤子需要一个模具。这东西是一类的,然后铸造金属取出来。这个东西是一个对象。一个对象有一个真实的内存地址空间。非静态的属性和方法在对象里面,我们注入的metal。也就是new之后才有的东西,而静态的属性和方法是附加在classA上的,在运行时编译读取。现在让我们回顾一下最早的例子。在普通方法中调用静态方法或变量实际上是在这个实例化对象中调用Test::showV(),只不过我们使用了self关键字。它仍然是一个静态进程而不是真正包含showV()方法的对象,所以当然不能获取到$this!那么,如何让父类A中的test()方法调用子类的who()方法呢?AA类{静态函数who(){echo__CLASS__."\n";}staticfunctiontest(){static::who();}}classBBextendsAA{staticfunctionwho(){echo__CLASS__."\n";}}BB::测试();//BB说的对,用static::关键字调用,static是开始运行时的类,不是方法定义时的类。这样就完成了后期静态绑定。此外,parent::和self::将转发这条链。AAA类{公共静态函数foo(){static::who();}publicstaticfunctionwho(){echo__CLASS__."\n";}}classBBBextendsAAA{publicstaticfunctiontest(){AAA::foo();父母::富();自我::富();}publicstaticfunctionwho(){echo__CLASS__."\n";}}classCCCextendsBBB{publicstaticfunctionwho(){echo__CLASS__."\n";}}CCC::测试();//AAA、CCC、CCCCCC继承BBB,BBB继承AAA。AAA中的foo()方法使用static::who()调用who()方法BBB中的test()执行三个调用。结果就是parent::foo()和self::foo()都把CCC传过去了,最后用的是CCC的who()方法。这个例子看起来很简单。绕一圈,但其实只有一个结论,如果父类使用static关键字调用父类和子类都有的内容,那么就看外面是哪个子类调用了,就像一个方法的调用一样普通班。反之,self是基于self关键字所在的类。说了这么多,也算是把静态特性解释的差不多了。在实际应用中,还是需要综合考虑。静态属性和方法不可能因为静态属性的方便而全部使用或者根本不用。还是需要根据各种业务需求进行选择。具体代码:https://github.com/zhangyue0503/php/blob/master/newblog/php-static.php关注公众号:【硬核项目经理】获取最新文章添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费PHP、项目管理学习资料知乎、公众号、抖音、头条搜索【硬核项目经理】B站ID:482780532