PHP关于对象访问静态方法、属性等问题
为何有这样的问题呢?源自一段代码,如下:
class A
{
// public static $name = 'wangyumeidsb'; public $name = 'woaini'; public static function foo()
{
echo __CLASS__;
} public function test()
{
self::foo();
echo '---';
$this->foo();
echo '<hr>';
// echo 'this is A<br>'."\n";
} public function say()
{
echo '我是非静态方法';
}
} class B extends A
{
public function who()
{
A::test();
A::foo();
// echo A::$name;
echo $this->name; //
parent::test();
self::test();
$this->test(); //self并不是必须调用static,非静态也能调用?
}
} // A::say();
$b = new B;
$b->who();
// echo 'this is non-static property'.$b->name.'<br>';
// echo A::$name;
echo '>>>>>>>>>>>>>>>>';
$a = new A;
$a->test();
$a->foo();
A::foo(); // A::test(); //在类的外部:静态访问方式不能访问非静态方法。。。但是菲静态访问方式可以访问静态方法。。。
列出几个问题:
- 为何可以使用A::test();这种方式访问非静态方法test()?
- self::test();虽然说B要继承A的test方法,但是test不是静态方法,不归类所有,为何这种方式也可以访问?self不是必须访问静态成员吗,也可以访问非静态?那self指向的是什么?
手册说明 : 静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)。就像其它所有的 PHP 静态变量一样,静态属性只能被初始化为文字或常量,不能使用表达式。所以可以把静态属性初始化为整数或数组,但不能初始化为另一个变量或函数返回值,也不能指向一个对象。
在手册中看到了一个以前不知道的访问方式--------可以使用$foo::$name;来调用静态属性。$foo是对象啊!
class Foo
{
public static $name = 'so ga';
public function _foo()
{
echo self::$name;
}
} $foo = new Foo;
print $foo::$name;
$foo::_foo(); //调用可以输出值,,但是会报一个E_STRICT 级别的错误,,不会终止程序执行。。
$foo->_foo();
我把A:: 称为静态访问方式,把$a-> 称为非静态访问方式。下面都这样理解。
总结:在类的外部,静态访问方式可以访问静态方法,不能访问非静态方法(能够执行,但是用静态方式调用一个非静态方法会导致一个 E_STRICT
级别的错误。);非静态访问方式既可以访问静态方法,又可以访问非静态方法。
静态访问方式可以访问静态属性,不可以访问非静态属性;非静态访问方式可以访问非静态属性,不能访问静态属性。
在类的内部,静态访问方式既可以访问静态方法又可以访问非静态方法;非静态访问方式既可以访问静态方法,又可以访问非静态方法。
静态访问方式只能访问静态属性,不可以访问非静态属性;非静态访问方式可以访问非静态属性,不能访问静态属性。
更新:看到了鸟哥的一篇博客:http://www.laruence.com/2012/06/14/2628.html (尽量要避免使用”::”来调用一个非静态的方法)
附加:在手册中看到的一句话,同一个类的对象即使不是同一个实例也可以互相访问对方的私有与受保护成员。这是由于在这些对象的内部具体实现的细节都是已知的。(访问控制)
——————————————————更新补充——————————————————
class Test
{
private static $instance ; // construct 设置成私有
public function __construct()
{
if(self::$instance === null){
self::$instance = 888;
}
return self::$instance;
} public static function visit()
{
echo '<hr>';
echo 'ok';
echo self::$instance;
echo (new self)->aaa();
echo '<hr>';
} public function aaa()
{
echo __METHOD__;
echo self::$instance;
}
}
$t3 = Test::visit(); //输出的结果不一样,output:okTest::aaa888
$t3 = Test::visit(); //output:ok888Test::aaa888
$t3 = Test::visit();
为什么两次调用静态方法输出结果不同,分析了一下:因为调用静态方法不会触发构造函数,所以第一次没有执行到new操作的时候,静态属性$instance没有值。然后new self就调用了构造函数,初始化了$instance,而$instance是归类所有的。所以当第二次调用静态方法的时候,他就有值了。所以输出888。
class Test
{
private static $instance ; // construct 设置成私有
public function __construct()
{
if(self::$instance === null){
self::$instance = 888;
}
return self::$instance;
} public static function visit()
{
echo '<hr>';
echo 'ok';
echo self::$instance;
echo (new self)->aaa();
echo '<hr>';
} public function aaa()
{
echo __METHOD__;
echo self::$instance;
}
} $t = new Test;
$t->visit();
而像这种实例化对象来访问静态方法,在实例化的时候就已经触发了构造函数,所以第一次访问$instance就有值。
最新文章
- Unity Animation System(动画系统)
- POJ-3041
- 阿里云推荐码 hut29f
- selenium-pageobject设计模式
- UI入门指引
- iOS_UITableView性能优化那些事
- pentaho cde 封装自定义图形控件,动态传参
- CSS基础篇
- 如何利用ArcGIS Engine接口实现打开Raster Catalog中的某一幅指定的影像?
- python arguments *args and **args ** is for dictionaries, * is for lists or tuples.
- TCP/IP详解学习笔记(11)-- TFTP:简单文本传输协议,BOOTP:引导程序协议
- python自学笔记二
- $.cookie(&#39;name&#39;, null) 删除cookie 失效问题
- JS(三)
- jstl标签的fmt:formatDate格式化日期 String to Date
- 游戏对象、组件和Prefabs
- 关于MAC设置免费的动态壁纸
- 201521123122 《java程序设计》第十一周学习总结
- ASP.net core 2.0.0 中 asp.net identity 2.0.0 的基本使用(四)—用户注册
- awk进阶整理