php-精华-新特性,php-精华-新特性?

jackxiang 2009-10-23 19:44 | |
self访问类内部static变量 ,不想用全局变量, 暂时这样搞了!


1.__autoload 自动加载文件

        类名和文件名需要一致
                /**
                 * this function can auto load class file
                 * @param string $class_name    the param is a class_name in the class new process
                 * @author andy
                 */
                function __autoload( $str_class_name ) {
                    if ( file_exists( ROOTPATH."kernel/".$str_class_name.".class.php" ) ) {
                        require_once( ROOTPATH."kernel/".$str_class_name.".class.php" );

                    } else if ( file_exists( ROOTPATH."kernel/".strtolower( $str_class_name )."/".$str_class_name.".class.php" ) ){
                        require_once( ROOTPATH."kernel/".strtolower( $str_class_name )."/".$str_class_name.".class.php" );

                    } else if ( file_exists( ROOTPATH."common/".strtolower( $str_class_name )."/".strtolower( $str_class_name ).".php" ) ){
                        require_once( ROOTPATH."common/".strtolower( $str_class_name )."/".strtolower( $str_class_name ).".php" );
                    }
                }


2.__construct,__destruct

构造函数,析构函数


3.__clone,clone

        对象的克隆
                $obj_test2 = clone $obj_test1;


4.public,private,protected,final

        公共模式(Public):允许在对象外部进行操作控制。  
        私有模式(Private):只允许本对象内的方法对其进行操作控制。  
        受保护模式(Protected):允许本对象及其父对象对其进行操作控制。

        public     公有的,由它声明的方法和数据可以在对类外部调用,起到接口的作用.
        protected 受保护类型,声明的方法可以被叫它所继程类访问,但不能在外部访问.
        private    私有类型,声明的方法和数据只能在本类中进行访问.

        static     声明静态变量或对象要用到.声明后可以作为全局变量来使用.

        public     是公有的 private是私有的 这些关键字用于声明类和成员的可见性。public成员可以被任何类访问,
        protected 成员限于自己和子类访问,
        private    成员限于自己访问。
        final      关键字是限制访问成员方法的另一个方法。子类不能覆写父类中标识为final的方法,Final关键字不能用于属性。


5.interface,implements 接口

        接口不具体实现方法,只定义方法
        一个类可继承多个接口
                interface displayAble {
                    function display();
                }
                interface printAble {
                    function doPrint();
                }
                class foo implements displayAble,printAble {
                    function display() {
                        echo "display";
                    }
                    function doPrint() {
                        echo "doPrint";
                    }
                }


6.extends 类继承

        不支持多重继承
                class Dog extends Mammal {
                    ...
                }


7.抽象类及与接口区别

        抽象类不能被实例化。  
        抽象类与其它类一样,允许定义变量及方法。  
        抽象类同样可以定义一个抽象的方法,抽象类的方法不会被执行,不过将有可能会在其派生类中执行。
        抽象类不能多重继承, 要多重继承就得使用接口.
        抽象类, 再抽象也还属于类的范畴, 它能包含一个类能包含的任何东西;
        而接口已经不属于类了, 它是类的抽象.

        abstract class表示的是"is a"关系,interface表示的是"like a"关系

        门的基本属性是开和关, 所以放在抽象类里, 即所谓的"is a", 报警器只是门的功能, 所以放接口里, 即所谓的"like a"

        最最本质的东西在抽象类中定义,行为在接口中定义,原因是最本质的东西永远不变,所以能满足抽象类的单继承性,行为是不断地增加的,所以放在接口中。
        门最本质的东西是能开能关,报警有些门有这种行为,有些没有,所以只能是定在接口中了


8.__call

        这个方法用来监视一个对象中的其它方法。
        如果试着调用一个对象中不存在的方法,__call 方法将会被自动调用

                class foo {
                    function __call($name,$arguments) {
                        print("Did you call me? I'm $name!");
                    }
                }
                $x = new foo();
                $x->doStuff();
                $x->fancy_stuff();

        实现“过载”动作  
        这个特殊的方法可以被用来实现“过载(overloading)”的动作,这样就可以检查参数并且通过调用一个私有的方法来传递参数。

                class Magic {
                    function __call($name,$arguments) {
                        if($name=='foo') {
                            if(is_int($arguments[0])) $this->foo_for_int($arguments[0]);
                            if(is_string($arguments[0])) $this->foo_for_string($arguments[0]);
                        }
                    }
                    private function foo_for_int($x) {
                        print("oh an int!");
                    }
                    private function foo_for_string($x) {
                        print("oh a string!");
                    }
                }
                $x = new Magic();
                $x->foo(3);
                $x->foo("3");

                //out put
                oh an int!oh a string!


9.__set,__get

__set 和 __get 方法可以用来捕获一个对象中不存在的变量和方法


10.异常处理

        try {
            $error = 'Always throw this error';
            throw new Exception($error);
            //从这里开始,try 代码块内的代码将不会被执行
            echo 'Never executed';
        } catch (Exception $e) {
            echo 'Caught exception: ', $e->getMessage(), "\n";
        }
        //继续执行
        echo 'Hello World';

        例[1] 用 try...catch
                $dsn = 'mysql:host=localhost;dbname=testdb';
                $user = 'dbuser';
                $password = 'dbpass';
                try {
                    $dbh = new PDO($dsn, $user, $password); //创建数据库连接对象容易出现异常
                    echo '如果上面出现异常就不能显示我了';
                } catch (PDOException $e) {
                    echo 'Connection failed: ' . $e->__toString();
                }

        例[2] try..catch 和 throw一起用
                try {
                   $error = '我抛出异常信息,并且跳出try块';
                   if(is_dir('./tests')){
                        echo 'do sth.';
                   }else{
                       throw new Exception($error,12345);
                   }
                   echo '上面有异常的话就轮不到我了!~
                ',"\n";
                } catch (Exception $e) {
                   echo '捕获异常: ', $e->getMessage(),$e->getCode(), "\n
                "; //显示$error和123456
                }
                echo '继续执行';


11.类常量

        const定义类常量
                class Foo {
                    const constant = "constant";
                }
                echo "Foo::constant = " . Foo::constant . "\n";

        常量和其他变量的区别主要在于:
        1.类的实例化对象是不能改变常量的值,并且每个实例化对象的常量值都是相同的。
        2.不需要$符号来声明和使用常量。
        3.常量不能被类的实例化对象直接使用,它只能在类内部使用。这点跟static成员是一相同的。


12.魔术常量

        __METHOD__
                类方法名

        __FUNCTION__
                函数名

        __CLASS__
                类名

        DIRECTORY_SEPARATOR
                目录分隔符

        PATH_SEPARATOR
                路径分隔符

        __FILE__
                原文件路径

        __LINE__
                所在行数


13.static关键字,类的静态成员

        将一个类的属性或者方法定义为static,则可以在不实例化类的情况下使用类的属性和方法。
        1、static关键字必须在public、protected、private之后声明。
        2、子类不能重新定义父类中static关键字修饰的变量属性或者方法,除非将它们定义为static成员。
        3、static方法或者变量中,$this 变量是不可用的,如果要使用同一类中其他的定义为static变量或者方法,可以使用self::(变量名|方法名)来访问static成员。
        4、Static成员属性不能以$object->(static成员属性)方式访问,可以$类名::(static成员属性)访问它们。这里跟java不同,PHP中static成员是不能被类的实例对象访问的。

        类的静态成员与一般的类成员不同: 静态成员与对象的实例无关,只与类本身有关。他们用来实现类要封装的功能和数据,但不包括特定对象的功能和数据,静态成员包括静态方法和静态属性。
        静态属性包含在类中要封装的数据,可以由所有类的实例共享。实际上,除了属于一个固定的类并限制访问方式外,类的静态属性非常类似于函数的全局变量
        静态方法则实现类需要封装的功能,与特定的对象无关. 静态方法非常类似于全局函数


14.self::,parent::

        class FatherClass
        {
            const CONST_VALUE = 'FatherClass.const';
            static $static = "FatherClass.static";

            private function goPrivate(){
                echo "FatherClass.goPrivate
";
            }
            protected function goProtected() {
                echo "FatherClass.goProtected
";
            }
            function goPublic() {
                echo "FatherClass.goPublic
";
                self::goPrivate();//self关键字访问内部私有方法
                self::goProtected();//self关键字访问内部保护方法
                echo self::CONST_VALUE."
";//self访问类内部常量
                echo self::$static."
";//self访问类内部static变量
            }
        }

        class SunClass extends FatherClass
        {
            function goPrivate(){
                echo "重载父类方法:SunClass.goPrivate
";
                parent::goPrivate();//Fatal error
                parent::goProtected();//parent访问父类protected方法
                echo parent::CONST_VALUE."
";//parent访问父类常量
                echo parent::$static."
";//parent访问父类static变量
            }
        }

        FatherClass::goPrivate();//这里会出现Fatal error:,因为private修饰的成员外部是不能访问的。
        FatherClass::goProtected();//这里会出现Fatal error:,因为protected修饰的成员外部是不能直接访问的,只有子类或者类本身才能访问。
        echo FatherClass::CONST_VALUE."
";//通过::访问到类内部常量
        echo FatherClass::$static."
";//访问类的static变量
        FatherClass::goPublic();//访问类成员方法
        $sunclass = new SunClass();
        $sunclass->goPrivate();


15.__sleep,__wakeup 对象串行化

        串行化可以把变量包括对象,转化成连续bytes数据,可以将串行化后的变量存在一个文件里或在网络上传输,然后再反串行化还原为原来的数据。
        在反串行化类的对象之前定义的类,PHP可以成功地存储其对象的属性和方法. 有时可能需要一个对象在反串行化后立即执行。
        为了这样的目的,PHP会自动寻找__sleep和__wakeup方法。

        当一个对象被串行化,PHP会调用__sleep方法(如果存在的话). 在反串行化一个对象后,PHP 会调用__wakeup方法.
        这两个方法都不接受参数. __sleep方法必须返回一个数组,包含需要串行化的属性. PHP会抛弃其它属性的值。如果没有__sleep方法,PHP将保存所有属性。

        例子1显示了如何用__sleep和 __wakeup方法来串行化一个对象. Id属性是一个不打算保留在对象中的临时属性.
        __sleep方法保证在串行化的对象中不包含id属性. 当反串行化一个User对象,__wakeup方法建立id属性的新值.
        这个例子被设计成自我保持. 在实际开发中,可能发现包含资源(如图像或数据流)的对象需要这些方法。

                Listing1 Object serialization
                class User
                {
                 public $name;
                 public $id;

                 function __construct()
                 {
                  //give user a unique ID 赋予一个不同的ID
                  $this->id = uniqid();
                 }

                 function __sleep()
                 {
                  //do not serialize this->id 不串行化id
                  return(array("name"));
                 }

                 function __wakeup()
                 {
                  //give user a unique ID
                  $this->id = uniqid();
                 }
                }

                //create object 建立一个对象
                $u = new User;
                $u->name = "Leon";
                //serialize it 串行化 注意不串行化id属性,id的值被抛弃
                $s = serialize($u);
                //unserialize it 反串行化 id被重新赋值
                $u2 = unserialize($s);
                //$u and $u2 have different IDs $u和$u2有不同的ID
                print_r($u);
                print_r($u2);

作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/2096/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!

评论列表
发表评论

昵称

网址

电邮

打开HTML 打开UBB 打开表情 隐藏 记住我 [登入] [注册]