一、静态局部变量、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 ==> 指向最后一次重写的类,后期绑定
*/