• PHP 类与对象 全解析( 二)


    目录

    PHP 类与对象 全解析( 一)

    PHP 类与对象 全解析( 二)

    PHP 类与对象 全解析(三 )

    7.Static关键字


    声明类成员或方法为static,就可以不实例化类而直接访问。不能通过一个对象来访问其中的静态成员(静态方法除外)。

    静态成员属于类,不属于任何对象实例,但类的对象实例都能共享。
    小结:

    在类内部访问静态成员属性或者方法,使用 self::(没有 $ 符号),如:
     self:: $country  //类内部访问静态成员属性
     self:: myCountry()
    在子类访问父类静态成员属性或方法,使用 parent::(没有 $ 符号),如:
     parent:: $country
     parent:: myCountry()
    外部访问静态成员属性和方法为 类名/子类名:: ,如:
     Person::$country
     Person::myCountry()
     Student::$country
    但静态方法也可以通过普通对象的方式访问

        <?php  
          
        Class Person{  
            // 定义静态成员属性  
            public static $country = "中国";  
            // 定义静态成员方法  
            public static function myCountry() {  
                // 内部访问静态成员属性  
                echo "我是".self::$country."人<br />";  
            }  
        }  
        class Student extends Person {  
            function study() {  
                echo "我是". parent::$country."人<br />";  
            }  
        }  
        // 输出成员属性值  
        echo Person::$country."<br />";     // 输出:中国  
        $p1 = new Person();  
        //echo $p1->country;            // 错误写法  
        // 访问静态成员方法  
        Person::myCountry();            // 输出:我是中国人  
        // 静态方法也可通过对象访问:  
        $p1->myCountry();  
          
        // 子类中输出成员属性值  
        echo Student::$country."<br />";    // 输出:中国  
        $t1 = new Student();  
        $t1->study();           // 输出:我是中国人  
          
        ?>  

    ---------------------------------------------------

    8.抽象类    PHP5支持抽象类和抽象方法。


          抽象类不能直接被实例化,你必须先继承该抽象类,然后再实例化子类。
          抽象类中 至少要包含一个抽象方法。如果类方法被声明为抽象的,那么其中就不能包括具体的功能实现。
          继承一个抽象类的时候,子类必须实现抽象类中的所有抽象方法;
          另外,这些方法的可见性 必须和抽象类中一样(或者更为宽松)。
          如果抽象类中某个抽象方法被声明为protected,那么子类中实现的方法就应该声明为protected或者public,而不 能定义为private。
          //抽象方法:abstract protected function getValue();
    例子1

        abstract class AbstractClass{  
            // 定义抽象方法  
            abstract protected function getValue();  
            // 普通方法  
            public function printOut(){  
                print $this->getValue()."<br />";  
            }  
        }  
        class ConcreteClass extends AbstractClass{  
            protected function getValue(){  
                return "abstract ";//抽象方法的实现  
            }  
        }  
          
        $class1 = new ConcreteClass;  
        $class1->printOut();  

    例子2

        abstract class AbstractClass  
        {  
         // 强制要求子类定义这些方法  
            abstract protected function getValue();  
            abstract protected function prefixValue($prefix);  
          
            // 普通方法(非抽象方法)  
            public function printOut() {  
                print $this->getValue() . "
    ";  
            }  
        }  
          
        class ConcreteClass1 extends AbstractClass  
        {  
            protected function getValue() {  
                return "ConcreteClass1";  
            }  
          
            public function prefixValue($prefix) {  
                return "{$prefix}ConcreteClass1";  
            }  
        }  
          
        class ConcreteClass2 extends AbstractClass  
        {  
            public function getValue() {  
                return "ConcreteClass2";  
            }  
          
            public function prefixValue($prefix) {  
                return "{$prefix}ConcreteClass2";  
            }  
        }  
          
        $class1 = new ConcreteClass1;  
        $class1->printOut();  
        echo $class1->prefixValue('FOO_') ."
    ";  
          
        $class2 = new ConcreteClass2;  
        $class2->printOut();  
        echo $class2->prefixValue('FOO_') ."
    ";  

    /*
     * 抽象类不能直接被实例化,你必须先继承该抽象类,然后再实例化子类。
          抽象类中 至少要包含一个抽象方法。如果类方法被声明为抽象的,那么其中就不能包括具体的功能实现。
          继承一个抽象类的时候,子类必须实现抽象类中的所有抽象方法;
          另外,这些方法的可见性 必须和抽象类中一样(或者更为宽松)。
          如果抽象类中某个抽象方法被声明为protected,那么子类中实现的方法就应该声明为protected或者public,而不 能定义为private。
     *
     */

        class Person {  
            public $name;  
            public $age;  
          
            function say() {  
                echo "my name is:".$this->name."<br />";  
            echo "my age is:".$this->age;  
            }  
        }  

    // 类的继承

        class Student extends Person {  
            var $school;    //学生所在学校的属性  
              
            function study() {  
                echo "my name is:".$this->name."<br />";  
                echo "my shool is:".$this->school;  
            }         
        }  
          
        $t1 = new Student();  
        $t1->name = "zhangsan";  
        $t1->school = "beijindaxue";  
        $t1->study();  

    ---------------------------------------------------------------------


    9.接口


     接口定义:方法和常量值定义的集合
                  通过interface来定义一个接口,就像定义一个标准的类一样,但其中定义所有的方法都是空的。
       
     接口的特性:接口中定义的所有方法都必须是public
     
     接口的实现:一个接口可以使用implements操作符,类中必须实现接口中的所有方法,否则会报fatal错误,如果要实现多个接口,可以使用逗号来分隔多个接口的名称。

    抽象类和接口的区别

    接口是特殊的抽象类,也可以看做是一个模型的规范。接口与抽象类大致区别如下:

    1.一个子类如果 implements 一个接口,就必须实现接口中的所有方法(不管是否需要);如果是继承一个抽象类,只需要实现需要的方法即可。
    2.如果一个接口中定义的方法名改变了,那么所有实现此接口的子类需要同步更新方法名;而抽象类中如果方法名改变了,其子类对应的方法名将不受影响,只是变成了一个新的方法而已(相对老的方法实现)。
    3.抽象类只能单继承,当一个子类需要实现的功能需要继承自多个父类时,就必须使用接口。
    实例1:
    // 声明一个'iTemplate'接口

    nterface iTemplate  
    {  
        public function setVariable($name, $var);  
        public function getHtml($template);  
    }  

    // 实现接口
    // 下面的写法是正确的

        class Template implements iTemplate  
        {  
            private $vars = array();  
            
            public function setVariable($name, $var)  
            {  
                $this->vars[$name] = $var;  
            }  
            
            public function getHtml($template)  
            {  
                foreach($this->vars as $name => $value) {  
                    $template = str_replace('{' . $name . '}', $value, $template);  
                }  
           
                return $template;  
            }  
        }  

    实例2:
    //定义接口

        interface User{  
             function getDiscount();  
             function getUserType();  
         }  

    //VIP用户 接口实现

        class VipUser implements User{  
            // VIP 用户折扣系数  
            private $discount = 0.8;  
            function getDiscount() {  
                return $this->discount;  
            }  
            function getUserType() {  
                return "VIP user";  
            }  
        }  
        class Goods{  
            var $price = 100;  
            var $vc;  
            //定义 User 接口类型参数,这时并不知道是什么用户  
            function run(User $vc){  
                $this->vc = $vc;  
                $discount = $this->vc->getDiscount();  
                $usertype = $this->vc->getUserType();  
                echo $usertype."goods Price:".$this->price*$discount;  
            }  
        }  
          
        display ->run(new VipUser);    //可以是更多其他用户类型  

    -------------------------------------------------------------


    10.重载


       定义:一个类中的方法与另一个方法名称相同,但参数不同
       什么情况下执行重载?  当调用当前的环境下未被定义的属性或者方法时,或者当调用当前环境下不可见的属性或方法。
      
    提示:
     如果父类定义方法时使用了 final 关键字,则不允许被子类方法覆盖。

     访问父类被覆盖的方法
     可以通过parent:: 符号来访问父类被覆盖的方法或成员属性:
     //PHP 重载方法 __call()

     __call()(Method overloading)
    为了避免当调用的方法不存在时产生错误,可以使用 __call() 方法来避免。该方法在调用的方法不存在时会自动调用,程序仍会继续执行下去。

    语法:
    // __call()方法重载

        class Test{  
            public function __call($name,$args){  
             if($name== 'null' && count($args)==2 ){  
              $type='num';  
           foreach($args as $key => $val){  
               if(!(is_int($val) || is_float($val))){  
                $type= 'string';  
            }  
           }  
           $method=$name.ucfirst($type);  
           if(method_exists($this,$method),$args){  
               call_user_func_array(array($this,$method),$args);  
           }  
          }  
         }  
         public addNum($i,$j){  
             echo $i+$j;  
         }  
           
         public addString($i,$j){  
             echo $i.$j;  
         }  
        }  
        $test =new Test();  
        $test->add(3,4);  
        $test->add(3,'4');  
           

    案例:

        class MemberTest {  
                
            private $data = array();//被重载的数据保存在此    
            public $declared = 1;/**  重载不能被用在已经定义的属性  */  
            private $hidden = 2; /**  只有从类外部访问这个属性时,重载才会发生 */  
          
            public function __set($name, $value) {  
                echo "Setting '$name' to '$value'
    ";  
                $this->data[$name] = $value;  
            }  
          
            public function __get($name) {  
                echo "Getting '$name'
    ";  
                if (array_key_exists($name, $this->data)) {  
                    return $this->data[$name];  
                }  
          
                $trace = debug_backtrace();  
                trigger_error(  
                    'Undefined property via __get(): ' . $name .  
                    ' in ' . $trace[0]['file'] .  
                    ' on line ' . $trace[0]['line'],  
                    E_USER_NOTICE);  
                return null;  
            }  
          
            /**  PHP 5.1.0之后版本 */  
            public function __isset($name) {  
                echo "Is '$name' set?
    ";  
                return isset($this->data[$name]);  
            }  
          
            /**  PHP 5.1.0之后版本 */  
            public function __unset($name) {  
                echo "Unsetting '$name'
    ";  
                unset($this->data[$name]);  
            }  
          
            /**  非魔术方法  */  
            public function getHidden() {  
                return $this->hidden;  
            }  
        }  
          
          
        echo "<pre>
    ";  
          
        $obj = new MemberTest;  
          
        $obj->a = 1;  
        echo $obj->a . "
    
    ";  
          
        var_dump(isset($obj->a));  
        unset($obj->a);  
        var_dump(isset($obj->a));  
        echo "
    ";  
          
        echo $obj->declared . "
    
    ";  
          
        echo "Let's experiment with the private property named 'hidden':
    ";  
        echo "Privates are visible inside the class, so __get() not used...
    ";  
        echo $obj->getHidden() . "
    ";  
        echo "Privates not visible outside of class, so __get() is used...
    ";  
        echo $obj->hidden . "
    ";  

    //属性重载:__set(),__get(),__isset(),__unset()

        class Person{  
            private $data =array();  
            function __set($name,$value){  
             $this->data[$name]=$value;  
         }  
         function __get($name){  
             return $this->data[$name];  
         }  
        }  

    -----------------------------------------------------------------------------------


    11.对象迭代


           PHP5提供了一种迭代(iteration)对象的功能,就像使用数组那样,可以通过foreach 来遍历对象中的属性

        class MyClass  
        {  
            public $var1 = 'value 1';  
            public $var2 = 'value 2';  
            public $var3 = 'value 3';  
          
            protected $protected = 'protected var';  
            private   $private   = 'private var';  
          
            function iterateVisible() {  
               echo "MyClass::iterateVisible:
    ";  
               foreach($this as $key => $value) {  
                   print "$key => $value
    ";  
               }  
            }  
        }  
          
        $class = new MyClass();  
          
        foreach($class as $key => $value) {  
            print "$key => $value
    ";  
        }  
        echo "
    ";  
          
          
        $class->iterateVisible();  

    ---------------------------------------------------------------------------


    12.设计模式: 工厂模式和 单例模式,    观察者模式,命令链模式和策略模式

     命令链 模式以松散耦合主题为基础,发送消息、命令和请求,或通过一组处理程序发送任意内容。每个处理程序都会自行判断自己能否处理请求。
    如果可以,该请求被处理,进程停止。您可以为系统添加或移除处理程序,而不影响其他处理程序。


    工厂模式
        定义:工厂模式(Factory)允许你在代码执行时实例化对象。它之所以被称为工厂模式是因为它负责“生产”对象。工厂方法的参数是你要生成的对象对应的类名称。
     
    工厂模式语法:

        <?php  
        class Example  
        {  
            public static function factory($type)  
            {  
                if (include_once 'Drivers/' . $type . '.php') {  
                    $classname = 'Driver_' . $type;  
                    return new $classname;  
                } else {  
                    throw new Exception ('Driver not found');  
                }  
            }  
        }  
        ?>   

       工厂模式案例:

        <?php  
        interface IUser{  
         function getName();  
        }  
        class User implements IUser{  
         public function __construct($id){}  
         public function getName(){  
             return "haha";  
         }  
        }  
        class UserFactory{  
            public static function Create($id){  
          return new User($id);  
         }  
        }  
        $uo =UserFactory::Create(1);  
        echo $uo->getName();  
          
        ?>  

    单例
       定义三要素:1,某个类只能有一个实例  2,必须自行创建这个实例  3,必须自行向系统提供这个实例
      
       作用: 1,如果系统中需要有一个类来全局控制某些配置信息,那么使用单例模式可以很方便的实现。
              2,使用单例模式,可以避免大量的new操作消耗资源()
              3在一个页面请求中,便于调试,因为所有的代码都集中在一个类中(如数据库操作类) 可以在类中设置钩子,输出日志,从而避免到处都是var_dump
        
    单例模式(Singleton)用于为一个类生成一个唯一的对象。最常用的地方是数据库连接。 使用单例模式生成一个对象后,该对象可以被其它众多对象所使用。
    单件模式是我们在开发中经常用到的一种设计模式,利用PHP5面向对象的特性,我们可以很容易的构建单件模式的应用,下面是单件模式在PHP中的几种实现方法:

        class Stat{  
            static $instance = NULL;  
              
            static function getInstance(){  
                if(self::$instance == NULL){  
                    self::$instance = new Stat();  
                }  
                  
                return self::$instance;  
            }      
            private function __construct(){  
            }      
            private function __clone(){  
            }      
              
            function sayHi(){  
                return "The Class is saying hi to u ";  
            }  
        }  
          
          
        echo Stat::getInstance()->sayHi();   

    这是一种最通常的方式,在一个getInstance方法中返回唯一的类实例。

    对这里例子稍加修改,便可以产生一个通用的方法,只要叫道任何你想用到单件的类里,就可以了。

        class Teacher{  
            function sayHi(){  
                return "The teacher smiling and said 'Hello '";  
            }  
              
            static function getInstance(){  
                static $instance;  
                  
                if(!isset($instance)){  
                    $c = __CLASS__;  
                    $instance = new $c;  
                }          
                return $instance;  
            }  
        }  
          
        echo Teacher::getInstance()->sayHi();   

    最后一种是提供一个singleton类,然后通过调用getInstance方法,可以为任何一个类生产出一个实例来。

        class singleton{  
            function getInstance($class){  
                static $instances = array();  
                if(!array_key_exists($class,$instances)){  
                    $instances[$class] = &new $class;  
                }  
                $instance = $instances[$class];  
                  
                return $instance;  
            }  
        }  
          
        class People{  
            function sayHi(){  
                return 'Hello i am a people?';  
            }  
        }  
          
        echo "<br />";  
        echo singleton::getInstance('People')->sayHi();   

    通过这三种方法,我们可以很容易的应用单件模式,如果能够结合工厂模式,将使我们的编程变得更有条理和效率。
    ---------------------------------------------------------------------------------------

  • 相关阅读:
    转 linux设备模型(4)
    SQL convert
    SQL 中的 case when
    自己写的文本文件加密器
    [A3] 2D Airfoil Aerodynamic Analysis With Fluent & Gambit
    [A2]更快的使用你的键盘:AutoHotkey
    [A4]更快的使用你的键盘:AutoHotkey(2)
    开篇HOG提取训练检测+样本制作
    Flash调用Lua脚本: 五
    Sql Server全局变量 【转载】
  • 原文地址:https://www.cnblogs.com/easirm/p/4189261.html
Copyright © 2020-2023  润新知