ddxiami

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 5442|回复: 10

[细说PHP] 第10章PHP面向对象的程序设计--常见的关键字和魔术方法

[复制链接]
发表于 2013-8-6 15:30:40 | 显示全部楼层 |阅读模式
final关键字的应用:使用final标识的类不能被继承;在类中使用final标识的成员方法,在子类中不能被覆盖。


<?php
        final class MyClass {                    //声明一个类,并使用final关键字标识,使其不能有子类
                //成员略…
        }
        class MyClass2 extends MyClass {         //声明另一个类并试图去继承final标识的类,结果出错
                //成员略…
        }       
?>


<?php
        //声明一个类MyClass作为父类,在类中只声明一个成员方法
    class MyClass {     
                //声明一个成员方法并使用final标识,则不能在子类中覆盖
                final function fun() {      
                        //方法体中的内容略
                }
        }
       
        //声明继承MyClass类的子类,在类中声明一个方法去覆盖父类中的方法
        class MyClass2 extends MyClass {
                //在子类中试图去覆盖父类中已被final标识的方法,结果出错
                function fun() {            
                        //方法体中的内容略
                }
        }       
?>

回复

使用道具 举报

 楼主| 发表于 2013-8-6 16:19:29 | 显示全部楼层
static关键字的使用
在类中声明的成员方法中,也可以使用关键字“self”来访问其他静态成员。因为静态成员是属于类,而不属于任何对象,不能用$this引用它。

<?php
        //声明一个MyClass类,用来演示如何使用静态成员
        class MyClass {                        
                static $count;                       //在类中声明一个静态成员属性count,用来统计对象被创建的次数

                function __construct() {             //每次创建一个对象就会自动调用一次这个构造方法
                        self::$count++;                               //使用self访问静态成员count,使其自增1
                }

                static function getCount() {        //声明一个静态方法,在类外面直接使用类名就可以调用
                        return self::$count;                   //在方法中使用self访问静态成员并返回
                }
        }
        
        MyClass::$count=0;                                 //在类外面使用类名访问类中的静态成员,为其初始化赋值0

        $myc1 = new MyClass();                      //通过MyClass类创建第一个对象,在构造方法中将count累加1
        $myc2 = new MyClass();                       //通过MyClass类创建第二个对象,在构造方法中又为count累加1
        $myc3 = new MyClass();                       //通过MyClass类创建第三个对象,在构造方法中再次为count累加1
     
        echo MyClass::getCount();                      //在类外面使用类名访问类中的静态成员方法,获取静态属性的值 3
    echo $myc3->getCount();                     //通过对象也可以访问类中的静态成员方法,获取静态属性的值 3
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-6 16:27:33 | 显示全部楼层
单态设计模式
在很多操作中,比如建立目录、数据库连接都有可能会用到这种技术。

<?php
        /**
                声明一个类Db,用于演示单态模式的使用
        */
        class DB {
                private static $obj = null;                 //声明一个私有的,静态的成员属性$obj
               
                /* 构造方法, 使用private 封装后则只能在类的内部使用new去创建对象 */
                private function __construct() {
                        /* 在这个方法中去完成一些数据库连接等操作 */
                        echo "连接数据库成功<br>";
                }
               
                /* 只有通过这个方法才能返回本类的对象,该方法是静态方法,用类名调用 */
                static function getInstance() {
                        if(is_null(self::$obj))                        //如果本类中的$obj为空,说明还没有被实例化过
                                self::$obj = new self();        //实例化本类对象
                               
                        return self::$obj;                                //返回本类的对象
                }
               
                /* 执行SQL语句完成对数据库的操作 */
                function query($sql) {
                        echo $sql;
                }
        }
       
        //只能使用静态方法getInstance()去获取DB类的对象
        $db = DB::getInstance();
       
        //访问对象中的成员
        $db -> query("select * from user");
?>
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-6 16:54:11 | 显示全部楼层
const关键字
常量名通常是大写

<?php
        //声明一个MyClass类,在类中声明一个常量,和一个成员方法
        class MyClass {   
                 const CONSTANT = 'CONSTANT value';                  //使用const声明一个常量,并直接赋上初始值

                    function showConstant() {                         //声明一个成员方法并在其内部访问本类中的常量
                       echo  self::CONSTANT."<br>";                         //使用self访问常量,注意常量前不要加“$”
                    }
        }

        echo MyClass::CONSTANT . "<br>";                     //在类外部使用类名称访问常量,也不要加”$”
        $class = new MyClass();                                //通过类MyClass创建一个对象引用$class
        $class->showConstant();                                //调用对象中的方法
        // echo $class::CONSTANT;                                     //通过对象名称访问常量是不允许的

回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-6 16:57:52 | 显示全部楼层
instanceof关键字
使用这个关键字可以确定一个对象是类的实例、类的子类,还是实现了某个特定接口,并进行相应的操作。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-6 17:00:08 | 显示全部楼层
克隆对象

<?php
        class Person {                   
                private $name;     
                private $sex;              
                private $age;      

                function __construct($name="", $sex="", $age=1) {               
                        $this->name = $name;
                        $this->sex = $sex;
                        $this->age = $age;
                }
               
                //声明此方法则在对象克隆时自动调用,用来为新对象重新赋值
                function __clone() {        
                        $this->name = "我是".$that->name."的副本";        //为副本对象中的name属性重新赋值
                        $this->age = 10;                                  //为副本对象中的age属性重新赋值
                }               

                function say()  {                                    
                        echo "我的名字:".$this->name.",性别:".$this->sex.",年龄:".$this->age."<br>";
                }
        }

        $p1 = new Person("张三", "男", 20);         //创建一个对象并通过构造方法为对象中所有成员属性赋初值
        $p2 = clone $p1;                                 //使用clone克隆(复制)对象,并自动调用类中的__clone()方法
   
        $p1 -> say();                                   //调用原对象中的说话方法,打印原对象中的全部属性值
        $p2 -> say();                                    //调用副本对象中的说话方法,打印出克隆对象的全部属性值
?>
回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-6 17:11:48 | 显示全部楼层
类中通用的方法__toString()

<?php
        //声明一个测试类,在类中声明一个成员属性和一个__toString()方法
        class TestClass {                            
                   private $foo;                                     //在类中声明的一个成员方法

            function __construct($foo) {                //通过构造方法传值为成员属性赋初值
                $this->foo = $foo;                      //为成员属性赋值
                   }
  
                public function __toString() {                //在类中定义一个__toString方法
                return $this->foo;                      //返回一个成员属性$foo的值
                }
        }

        $obj = new TestClass('Hello');                     //创建一个对象并赋值给对象引用$obj
        echo $obj;                                             //直接输出对象引用则自动调用了对象中__toString()方法输出Hello

回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-6 17:22:27 | 显示全部楼层
__call()方法的应用

<?php
        //声明一个测试类,在类中声明printHello()和__call()方法
        class TestClass {                        
                function printHello() {                //声明一个方法,可以让对象能成功调用
                        echo "Hello<br>";               //执行时输出一条语句
                }
               
                /**
                        声明魔术方法__call(),用来处理调用对象中不存在的方法
                        @param        string        $functionName        访问不存的成员方法名称字符串
                        @param        array        $args                访问不存的成员方法中传递的参数数组
                */
                function __call($functionName, $args) {            
                        echo "你所调用的函数:".$functionName."(参数:";  //输出调用不存在的方法名
                        print_r($args);                                   //输出调用不存在的方法时的参数列表
                        echo ")不存在!<br>\n";                                 //输出附加的一些提示信息
                }       
        }

        $obj = new TestClass();                          //通过类TestClass实例化一个对象
        $obj -> myFun("one", 2, "three");   //调用对象中不存在的方法,则自动调用了对象中的__call()方法
        $obj -> otherFun(8,9);                   //调用对象中不存在的方法,则自动调用了对象中的__call()方法
        $obj -> printHello();                     //调用对象中存在的方法,可以成功调用

回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-6 17:29:01 | 显示全部楼层
声明一个DB类(数据库操作类)的简单操作模型,使用__call()方法

<?php
        //声明一个DB类(数据库操作类)的简单操作模型
        class DB {
                //声明一个私有成员属性数组,主要是通过下标来定义可以参加连贯操作的全部方法名称
                private $sql = array(
                        "field" => "",
                        "where" => "",
                        "order" => "",
                        "limit" => "", 
                        "group" => "",
                        "having" => ""
                        );
               
                //连贯操作调用field() where() order() limit() group() having()方法,组合SQL语句
                function __call($methodName, $args) {
                        //将第一个参数(代表不存在方法的方法名称),全部转成小写方式,获取方法名称
                        $methodName = strtolower($methodName);
                       
                        //如果调用的方法名和成员属性数组$sql下标对应上,则将第二个参数给数组中下标对应的元素
                        if(array_key_exists($methodName, $this->sql)) {
                                $this->sql[$methodName] = $args[0];
                        } else {
                                echo '调用类'.get_class($this).'中的方法'.$methodName.'()不存在';
                        }
                       
                        //返回自己对象,则可以继续调用本对象中的方法,形成连贯操作
                        return $this;                               
                }
               
                //简单的应用,没有实际意义,只是输出连贯操作后组合的一个SQL语句,是连贯操作最后调用的一个方法
                function select() {
                        echo "SELECT FROM {$this->sql['field']} user {$this->sql['where']} {$this->sql['order']}
                                  {$this->sql['limit']}  {$this->sql['group']}  {$this->sql['having']}";
                }
        }
       
        $db = new DB;       
       
        //连贯操作,也可以分为多行去连续调用多个方法
        $db -> field('sex, count(sex)')
                -> where('where sex in ("男", "女")')
                -> group('group by sex')
                -> having('having avg(age) > 25')
                -> select();
               
        //如果调用的方法不存在,也会有提示,下面演示的就是调用一个不存的方法query()
        $db -> query('select * from user');

回复 支持 反对

使用道具 举报

 楼主| 发表于 2013-8-6 17:34:23 | 显示全部楼层
自动加载类

<?php   
        /**
                声明一个自动加载类的魔术方法__autoload()
                @param        string        $className 需要加载的类名称字符串
        */
        function __autoload($className) {      
                //在方法中使用include包含类所在的文件
                include(strtolower($className).".class.php");
        }
       
        $obj  = new User();  //User类不存在则自动调用__autoload()函数,将类名“User”作为参数传入
        $obj2 = new Shop();         //Shop类不存在则自动调用__autoload()函数,将类名“Shop”作为参数传入
?>
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|技术文档库 ( 闽ICP备15017263号-2 )|网站地图

GMT+8, 2025-5-18 17:48 , Processed in 0.041263 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表