PHP关于对象访问静态方法、属性等问题

摘要:
ViewCode列出了几个问题:为什么我可以使用A::test();如何以这种方式访问非静态方法test()?与所有其他PHP静态变量一样,静态属性只能初始化为文本或常量,不能使用表达式。);非静态访问模式可以访问静态方法和非静态方法。

为何有这样的问题呢?源自一段代码,如下:PHP关于对象访问静态方法、属性等问题第1张

PHP关于对象访问静态方法、属性等问题第2张PHP关于对象访问静态方法、属性等问题第3张
 1 class A
 2 {
 3     // public static $name = 'wangyumeidsb';
 4 
 5     public $name = 'woaini';
 6 
 7     public static function foo()
 8     {
 9         echo __CLASS__;
10     }
11 
12     public function test()
13     {
14         self::foo();
15         echo '---'; 
16         $this->foo();
17         echo '<hr>';
18         // echo 'this is A<br>'."
";
19     }
20 
21     public function say()
22     {
23         echo '我是非静态方法';
24     }
25 }
26 
27 class B extends A
28 {
29     public  function who()
30     {
31         A::test();
32         A::foo();
33         // echo A::$name;
34         echo $this->name;    //
35         parent::test();
36         self::test();
37         $this->test();   //self并不是必须调用static,非静态也能调用?
38     }
39 }
40 
41 // A::say();
42 $b = new B;
43 $b->who();
44 // echo 'this is non-static property'.$b->name.'<br>';
45 // echo A::$name;
46 echo '>>>>>>>>>>>>>>>>';
47 $a = new A;
48 $a->test();
49 $a->foo();
50 A::foo();
51 
52 // A::test();    //在类的外部:静态访问方式不能访问非静态方法。。。但是菲静态访问方式可以访问静态方法。。。
View Code

列出几个问题:

  1. 为何可以使用A::test();这种方式访问非静态方法test()?
  2. self::test();虽然说B要继承A的test方法,但是test不是静态方法,不归类所有,为何这种方式也可以访问?self不是必须访问静态成员吗,也可以访问非静态?那self指向的是什么?

手册说明   : 静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)。就像其它所有的 PHP 静态变量一样,静态属性只能被初始化为文字或常量,不能使用表达式。所以可以把静态属性初始化为整数或数组,但不能初始化为另一个变量或函数返回值,也不能指向一个对象。

在手册中看到了一个以前不知道的访问方式--------可以使用$foo::$name;来调用静态属性。$foo是对象啊!

PHP关于对象访问静态方法、属性等问题第4张PHP关于对象访问静态方法、属性等问题第5张
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();
View Code

我把A::  称为静态访问方式,把$a->  称为非静态访问方式。下面都这样理解。

总结:在类的外部,静态访问方式可以访问静态方法,不能访问非静态方法(能够执行,但是用静态方式调用一个非静态方法会导致一个 E_STRICT 级别的错误。);非静态访问方式既可以访问静态方法,又可以访问非静态方法。

           静态访问方式可以访问静态属性,不可以访问非静态属性;非静态访问方式可以访问非静态属性,不能访问静态属性。

    在类的内部,静态访问方式既可以访问静态方法又可以访问非静态方法;非静态访问方式既可以访问静态方法,又可以访问非静态方法。

         静态访问方式只能访问静态属性,不可以访问非静态属性;非静态访问方式可以访问非静态属性,不能访问静态属性。

更新:看到了鸟哥的一篇博客http://www.laruence.com/2012/06/14/2628.html    (尽量要避免使用”::”来调用一个非静态的方法)

附加:在手册中看到的一句话,同一个类的对象即使不是同一个实例也可以互相访问对方的私有与受保护成员。这是由于在这些对象的内部具体实现的细节都是已知的。(访问控制

——————————————————更新补充——————————————————

PHP关于对象访问静态方法、属性等问题第6张PHP关于对象访问静态方法、属性等问题第7张
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();
View Code

为什么两次调用静态方法输出结果不同,分析了一下:因为调用静态方法不会触发构造函数,所以第一次没有执行到new操作的时候,静态属性$instance没有值。然后new self就调用了构造函数,初始化了$instance,而$instance是归类所有的。所以当第二次调用静态方法的时候,他就有值了。所以输出888。

PHP关于对象访问静态方法、属性等问题第8张PHP关于对象访问静态方法、属性等问题第9张
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();
View Code

而像这种实例化对象来访问静态方法,在实例化的时候就已经触发了构造函数,所以第一次访问$instance就有值。

免责声明:文章转载自《PHP关于对象访问静态方法、属性等问题》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇PHP中变量声明和定义的区别static后期静态绑定下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

sqlserver备份还原数据库时报占用错误

、做项目时遇到这种情形:原来的test_dev数据库,想复制出test_ft供测试用。此时备份test_dev出test_backup文件,想直接还原成test_ft时会报占用错误。 还原数据库:The backup set holds a backup of a database other than the existing database因为数据库正...

golang基础之一

一、第一个go程序 package main import ( "fmt" ) func main(){ fmt.Println("hello world") } 对于代码的解释 如果是为了将代码编译成一个可执行程序,那么package必须是main如果是为了将代码编译成库,那么package则没有限制g...

php环境配置 php5 MySQL5 apache2 phpmyadmin ZendOptimizer安装与配置

php环境的配置,对于新手来说,绝对是一件烦事.总会遇到这样那样的问题,走很多弯路.所以特意写了这个配置文档,相信按照以下步骤你一定会成功的.错误的地方也希望各位指正. 更多文章 php爱好者站 http://www.phpfans.net本例是在wiondws XP下 php5.2.1(zip)apache2.2.4MySQL5.0.37phpmyadmi...

ios storyboard全解析 (二)

Add Player 最终的设计看上去像下面这样:#接第一部分:原帖地址简书地址 如果你想了解storyboards,那么你来对地方了.在第一篇文章第一篇文章中,你已经学到了Interface Builder的基本用法来创建和连线多个控制器,以及使用在storyboard中可以通过直接创建自定义的tableViewCell.此次storyboard系列教程...

高级php面试题及部分答案

在网上看到一些高级php 的面试题目。。 闲来无事,搞了一些答案。。。可能不是很全面,留这以后备用吧。 一. 基本知识点1.1 HTTP协议中几个状态码的含义:503 500 401 403 404 200 301 302。。。200 : 请求成功,请求的数据随之返回。301 : 永久性重定向。302 : 暂时行重定向。401 : 当前请求需要用户验证。40...

PHP开发程序应该注意的42个优化准则

PHP 独特的语法混合了 C、Java、Perl 以及 PHP 自创新的语法。它可以比 CGI或者Perl更快速的执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML文档中去执行,执行效率比完全生成 HTML标记的CGI要高许多。下面介绍了42个程序的优化准则。1.如果一个方法可静态化,就对它做静态声明。速率可提升至4倍。2...