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就有值。
PHP关于对象访问静态方法、属性等问题的更多相关文章
- JavaScript对象访问器属性
对象访问器就是setter和getter,他们的作用就是 提供另外一种方法来获取或者设置对象的属性值, 并且在获取和设置的时候,可以用一定的其他操作. 看下面代码: <script> va ...
- javascript中对象访问自身属性的方式
在javascript中,通过对象的方法访问对象自身属性时,必须采用this.fieldName的方式. 原因是javascript中Function是无状态的,访问对象的属性时,必须指定当前的上下文 ...
- 007-对象—— static静态方法属性内存构成及使用方法讲解
<?php /* 7 对象 static静态方法属性内存构成及使用方法讲解 */ /*class a{ public $uname=11; static public function _a() ...
- JavaScript | 数据属性与访问器属性
属性类型 数据属性 - 包含一个数据值的位置,可以读取和写入值 [writable] 是否能修改属性的值 true [enumerable] 是否通过for in 循环返回属性(是否可以被枚举) tr ...
- python中类对象、实例对象、类属性、实例属性、类方法、实例方法、静态方法
类对象.类属性与实例对象.实例属性的区别 在Python中一切皆是对象,类是一个特殊的对象即类对象,描述类的属性称为类属性.类属性在内存中只有一份,在__init__外部定义. 通过类创建的对象称为实 ...
- 在实体对象中访问导航属性里的属性值出现异常“There is already an open DataReader associated with this Command which must be closed first”
在实体对象中访问导航属性里的属性值出现异常“There is already an open DataReader associated with this Command which must be ...
- javascript对象属性——数据属性和访问器属性
ECMA-262第五版在定义时,描述了属性property的各种特征,定义这些特性是为了实现javascript引擎用的,为了表示该特性是内部值,规范把它们放在了两对儿方括号中,例如[[Enumera ...
- 类实例化对象可以访问静态(static)方法,但是不能访问静态属性。
类-> 访问->静态方法(类的方法)->可以 类 ->访问->普通方法(对象的方法)->不可以(虽然方法里不用$this关键字时,可以!但不支持这种写法) 类-&g ...
- js对象的数据属性和访问器属性
js面向对象 ECMA-262第5版在定义只有内部才用的特性(attribute)时,描述了属性(property)的各种特征.ECMA-262定义这些特性是为了实现javascript引擎用的,因此 ...
随机推荐
- Durable NAND flash memory management
词条积累 1.NAND flash memory http://www.searchstorage.com.cn/whatis/word_6052.htm http://baike.baidu.com ...
- Java小技巧:怎么循环日期?
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");try{//起始日期Date start = sdf.parse ...
- C++四种类型转换总结
C风格的强制类型转换很简单,均用 Type b = (Type)a 形式转换.C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用,如下表: 转换类型操作符 作用 const_cast 去 ...
- poj2385(基础DP)
题目链接:http://poj.org/problem?id=2385 题意:最开始Bessie站在树1下面,每一个单位时间有颗苹果从树1或者树2上落下来.每个单位时间Bessie可以移动一次位置,时 ...
- Minimum Score Triangulation of Polygon
Given N, consider a convex N-sided polygon with vertices labelled A[0], A[i], ..., A[N-1] in clockwi ...
- 2019年8月22日 星期四(怎样成为PHP大牛)
1.服务器方面,各种PHP部署方案烂熟,Lvs,keepalived,nginx,apache,docker,换句话说其战力值相当于一个高级运维,迅速定位并排除PHP运行中的各种问题. 2.数据库方面 ...
- golang substring
在java下习惯了String.subString(start,end) 然后再golang继续敲substring木有了,看了下代码,也是原生支持的 但是百度发现有些人竟然把字符串转成字符数组再根据 ...
- ElasticSearch工作原理与优化
elasticsearch设计的理念就是分布式搜索引擎,底层其实还是基于lucene的,通过倒排索引的方式快速查询.比如一本书的目录是索引,然后快速找到每一章的的文本内容这种叫正向索引:而如果一件衣服 ...
- 多线程编程-- part 6 共享锁和ReentrantReadWriteLock
介绍: ReadWriteLock,顾名思义,是读写锁.它维护了一对相关的锁 — — “读取锁”和“写入锁”,一个用于读取操作,另一个用于写入操作.(1)“读取锁”用于只读操作,它是“共享锁”,能同时 ...
- 使用CLI 3 创建发布Web Components
本文翻译自:codementor 翻译不当之处,欢迎指正交流 Web Components是web平台的未来吗?关于这一问题支持和反对的观点有很多.事实上浏览器对Web Components的支持正在 ...