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引擎用的,因此 ...
随机推荐
- xshell设置
登录脚本: #定义rz,sz自动下载路径 #保持窗口活动状态, 空闲时每120秒发送一个回车
- C# while循环及for循环,for循环的嵌套,冒泡循环
循环四要素:初始条件.循环条件.循环体.状态改变 初始条件:开始进入循环 所需要的 第一次条件 循环条件:执行循环所需要满足的条件 循环体:每次循环要执行的代码 状态改变:执行完当前循环体后 循环条件 ...
- [爬虫] BeautifulSoup库
Beautiful Soup库基础知识 Beautiful Soup库是解析xml和html的功能库.html.xml大都是一对一对的标签构成,所以Beautiful Soup库是解析.遍历.维护“标 ...
- 2.更新YUM源
查看本地源 先删除本地所有源 下载源仓库文件,xxx.repo curl -o /etc/yum.repos.d/ali.repo http://mirrors.aliyun.com/repo/Cen ...
- java 利用辗除法求两个整数的最大公约数和最小公倍数
题目:输入两个正整数m和n,求其最大公约数和最小公倍数. 程序分析:利用辗除法. package Studytest; import java.util.Scanner; public class P ...
- PTA(Basic Level)1038.统计同成绩学生
本题要求读入 N 名学生的成绩,将获得某一给定分数的学生人数输出. 输入格式: 输入在第 1 行给出不超过 105 的正整数 N,即学生总人数.随后一行给出 N 名学生的百分制整数成绩,中间以空格分隔 ...
- [转帖]FreeBSD、OpenBSD、NetBSD的区别
FreeBSD.OpenBSD.NetBSD的区别 Linux 的历史 http://www.361way.com/unix-bsd/1513.html 一直unix在我心目中的地位都很高,uni ...
- 日期和时间(datetime模块)
前言: 参考:https://blog.csdn.net/weixin_42232219/article/details/89838580 在 python 中,datetime 是对日期数据进行处理 ...
- 坦克大战--Java类型 ---- (1)音乐播放
实现原理 我用接口java.applet.AudioClip实现音乐播放,那么我们需要了解这个接口的情况. 我们主要使用其中的三个方法: (1)void loop(); //循环播放(2)void p ...
- ELK视频下载
Elasticsearch , Logstash, Kibana 相关视频下载地址:Beats.Elastic Stack.ElasticSearch.Kibana.Logstash下载地址:链接:h ...