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引擎用的,因此 ...
随机推荐
- 云风协程库coroutine源码分析
前言 前段时间研读云风的coroutine库,为了加深印象,做个简单的笔记.不愧是大神,云风只用200行的C代码就实现了一个最简单的协程,代码风格精简,非常适合用来理解协程和用来提升编码能力. 协程简 ...
- Linux下面查看网卡的信息
查看linux下面网卡的速度信息 Study From 百度知道 (懒得翻墙) 1. centos机器 安装的比较全(个人比较懒 没有使用core最小化安装, 避免出问题麻烦 公司网络太垃圾) 使用 ...
- PLSQL中查到的数据和程序中查询到的不一样
1.首先看下你的修改或者新增的SQL是否提交.
- Java基础开篇
我是一个2019毕业的非计算机的毕业生,从大二开始喜欢上Java直到现在一直都在学习,Brid从小就对计算机感兴趣,可惜高中的时候不懂事,没有规划未来,考上了一所专科学院,然后大一并不能转专业,现在毕 ...
- Eclipse 新建.jsp页面后,页面头部标签报错的解决方法
Eclipse 新建.jsp页面后,页面头部标签报错的解决方法 1.报错地方: 2.解决方法: .jsp页面右键==>BUild Path ==>Configure Build Path. ...
- CentOS 7 配置 kcptun 实现网站加速
目的:shadowsocks+kcptun 实现vpn加速(shadowsocks,kcptun在同一台VPS上) 一.shadowsocks安装(参考 https://www.cnblogs.co ...
- eclipse运行jsp出现404错误怎么办?
Window/Show View/Other/Server/Servers/双击“Tomcat v7.0 Server at localhost”在Server Locations配置中选择第二个选项 ...
- FluentValidation在C# WPF中的应用
原文:FluentValidation在C# WPF中的应用 一.简介 介绍FluentValidation的文章不少,零度编程的介绍我引用下:FluentValidation 是一个基于 .NET ...
- 异常-throw的概述以及和throws的区别
package cn.itcast_06; /* * throw:如果出现了异常情况,我们可以把该异常抛出,这个时候的抛出的应该是异常的对象. * * throws和throw的区别(面试题) thr ...
- node-images Windows 64-bit with Unsupported runtime 错误解决办法 及 node 历史版本下载
在做项目的时候下载的最新的10.16[2019.6.12]版本,出现了模块不兼容的问题[node-images]. 在git上发现了相同问题 https://github.com/zhangyuanw ...