• 2009-08-27

    骏龙:php类的总结 - [技术空间]

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://www.blogbus.com/lily64-logs/45194989.html

    链接来源:http://bbs.php168.com/read.php?tid=238333

    以前学习php类的总结:
    1.php中不能重载,但是能用子类覆盖父类的方法名称来实现新的重载
    1.1 在子类中调用父类的覆盖部分可以使用 父类名称::方法名称();
    2.final 只能定义类和方法,不能使用final定义成员属性,因为final是常量的意思,在php里定义常量使用的是define函数
    2.1 final关键字标记的类不能被继承
    2.2 final关键字标记的方法不能被子类重写
    3.const是一个定义常量的关键字,在php中定义常量使用的是define()函数,但是在类里定义常量使用的是“const” 这个关键字
    3.1在程序中不能修改它的值。
    3.2 访问const 修饰的成员属性要使用类名,在本类的方法里使用“self”关键字,但不使用"$"符号,也不能使用对象来访问。
    4.static关键字可以描述类中的成员属性和成员方法
    4.1 static 的成员属于类,而不属于任何对象,
    4.2 static的成员是在类第一次被加载的时候分配的空间,其他类无法访问的,只对类的实例共享,能一定程度对类该成员形成保护
    4.3 静态成员放到了“初始化静态段”,在类第一次加载的时候放入的,可以让堆内存里的每个对象共享。所以在静态方法里,可以使用这个方法所在的类的“类名”,也可以使用“self”来访问其他静态成员。“self”代表这个静态方法所在的类。
    4.3.1 在类里的静态方法是不能访问类的非静态成员的。
    4.3.2 在类的非静态方法里可以访问静态成员:”self:成员属性“;
    4.4类的静态变量,非常类似全局变量,能够被所有类的实例共享,类的静态方法也是一样,类似于全局函数。
    4.5 在类内函数访问静态变量时前面加self::静态函数
    4.6 静态变量可以在类外直接访问,访问方法是类名::静态变量
    4.7 静态函数可以在类外直接访问,访问方式是类名::静态函数
    4.8 在类内静态函数访问另一个静态函数时使用 类名::静态函数名
    4.8.1 静态函数在类内访问静态变量时,访问方式是类名::静态变量
    4.8.2 静态函数在类内访问静态变量时,访问方式除了是类名::静态变量外,还可以使用self::静态变量
    4.9 在类内静态函数访问另一个静态函数时除了使用 类名::静态函数名外,还可以使用self::静态函数名,也可以直接调用静态函数
    4.10 静态函数内不能访问非静态变量
    4.11 在类内静态函数不能使用$this->非静态函数名访问非静态函数,可以使用self::非静态函数名
    4.12 
    5.类里的”$this“,在php里面提供了一个本对象的引用$this,每个对象里面都有一个对象的引用$this来代表这个对象,完成对象内部成员的调用。
    5.1 $this 就是对象内部代表这个对象的引用。
    6.类里"self",self 和$this相似,只不过self是代表这个静态方法所在的类,所以在静态方法里,可以使用这个方法所在的类的”类名“,也可以使用"self"来访问其他的静态成员,通常使用后者”self::成员属性“。
    7.类里”__“开头的函数名
    7.1类里”__“开头的函数名都是在某一时刻不同情况下自动调用执行的方法。
    7.2__toString()方法也是自动被调用,是直接输出对象引用时自动调用的。比如"$p = new Person()",直接用echo输出$p会产生错误,如果在类里定义了__toString()方法,再用echo直接输出对象引用的时候就不会产生错误了
    8.对象串行化
    8.1 __sleep()方法,在对象串行化的时候,会调用一个__sleep()方法来完成一些睡前的事情,__sleep()函数不接受任何参数,但返回一个数组,其中包含需要串行化的属性。未被包含的属性降在串行化时被忽略,如果没有__sleep()方法,php将保存所以属性.
    8.2 __wakeup()方法,在重新醒来时,即由二进制串重新组成一个对象的时候,则会自动调用__wakeup(),做一些对象醒来就要做的动作。
    8.3 有时你可能需要一个对象在反串行化后立即执行. 为了这样的目的,PHP会自动寻找__sleep和__wakeup方法.
    9. protected 成员能被同个类中的所有方法和继承出的类的中所有方法访问到,不能被父类的实例直接访问。protected and public 可以动态绑定
    10. private 大部分private属性仍然可以被外部代码共享. 解决方法是用一对public方法,一个是get(获取属性的值),另一个是set(设置属性的值). 
    10.1 private 不可以动态绑定。Private成员只存在于它们所在的类内部. 不像public和protected成员那样,PHP模拟静态绑定.
    10.2 什么时候用到private?private成员只有当你不想让子类继承改变或特殊化父类的行为时才用到,这种情况比你想像的要少, 通常来说,一个好的对象分层结构应当允许绝大多数功能被子类特殊化,改进,或改变—这是面向对象编程的基础之一。一定的情况下需要private方法或变量,例如当你确信你不想允许子类改变父类中的某个特定的部份。
    11.抽象类:抽象方法是就像子类中一般的方法的占位符(占个地方但不起作用),它与一般方法不同—没有任何代码. 如果类中存在一个或更多抽象方法, 那么这个类就成了抽象类. 你不能实例化抽象类. 你必须继承它们,然后实例化子类. 你也可以把抽象类看成是子类的一个模板.
    如果你覆写所有的抽象方法, 子类就变成一个普通的类. 如果没有覆写所有方法, 子类仍是抽象的. 如果一个类中中包含有抽象方法(哪怕只有一个), 你必须声明这个类是抽象的, 在class关键字前加上abstract.
    声明抽象方法的语法与声明一般方法不同. 抽象方法的没有像一般方法那样包含在大括号{}中的主体部份,并用分号;来结束.
    12.接口:如果你建立了一个只有抽象方法的类,你就定义了一个接口(interface). 为了说明这种情况, PHP中有interface 和implements关键字. 你可以用interface来代替抽象类, 用implements来代替extends来说明你的类定义或使用一个接口. 例如, 你可以写一个myClass implements myIterface. 这两种方法可以依个人偏爱来选择.
    12.1 如果接口中出现非抽象方法.会报错
    12.2 接口中的方法默认是public 型的.其它类型的修饰符,不能修饰接口中的抽象方法.
    12.3 即使接口中所有的方法都是抽象方法,也不能使用 abstract 修饰.也不能用final
    12.4 即使接口中所有的方法都是抽象方法,在接口中,可以声明静态方法.
    12.5 在接口中可以有常量,e.g.:
    <?
    interface User{
    const MAX_GRADE = 99;
      function getName();
      function setName($_name); 
    }
    ?>
    13.Namespace关键字给一块代码命名. 在这个代码块外部,脚本必须用操作符::加上命名空间的名称来引用这个代码块. 引用静态的类成员也是用相同的方法. 在命名空间内代码不需要声明命名空间, 它本身就是默认的. 这种方法比添加前缀的方法好. 你的代码可由此变得更加紧凑和可读.
    你可能想知道是否可以建立分层的(嵌套的)命名空间. 答案是不可以. 但你可以在命名空间名称后加上冒号, 你可以再次调用在名称中不包含冒号的变量,函数和类. 命名空间允许存在冒号,只要不是第一个字符和最后一个字符或接着另一个冒号. 命名空间的名称中的冒号对于PHP来说没有任何意义, 但如果你用他们来区分逻辑上的区块, 他们可以很好地说明你的代码中的父子(parent-child)关系.
    14. __toString()打印对象会调用它的__toString方法.
    15.不能实例化的类
    <?
    //
    //当__construct()为public时可以实例化
    class A{
      private function __construct(){}  
    }
    $a = new A();//fail
    ?>
    15.1
    //static的方法留给外部访问.<br><br>
    <?
    class A{
      private function __construct(){}
      static function getClassA(){
      return "这里是后门,可以通过这里进入类内部..";
      }  
    }
    echo A::getClassA();
    ?>
    15.2
    //不能用new实例化的类.<br>
    //static的方法留给外部访问.<br>
    //在方法内部返回实例.<br><br>
    <?
    class A{
      private function __construct(){
       
      echo "this is construction<br>\n";
      }
      static function getClassA(){
      $a = new A();
      return $a;
      }  
    }
    // 看到这里确实返回的是 A 的实例.但不是同一个对象.
    $a1 = A::getClassA();
    $a2 = A::getClassA();
    echo "\$a1 的类是 ".get_class($a1)." , \$a2 是 ".get_class($a1);
    if($a1 === $a2){ 
      echo "<br> \$a1 \$a2 指向同一对象.";
    }else{ 
      echo "<br> \$a1 \$a2 不是一个对象.";
    }
    //this is construction
    //this is construction
    //$a1 的类是 A , $a2 是 A
    //$a1 $a2 不是一个对象. 
    ?>
    15.3
    //不能用new实例化的类.<br>//static的方法留给外部访问.<br>
    //在方法内部返回实例.<br>
    //定义静态属性保证这个实例能被静态方法调用.<br>
    //增加判断部分.<br><br>
    <?
    class A{
    private static $a = null;
      private function __construct(){}
      static function getClassA(){
      if( null == self::$a){
      self::$a = new A();
      }  
      return self::$a;
      }  
    }
    // 看到这里确实返回的是 A 的实例.但不是同一个对象.
    $a1 = A::getClassA();
    $a2 = A::getClassA();
    echo "\$a1 的类是 ".get_class($a1)." , \$a2 是 ".get_class($a1);
    if($a1 === $a2){ 
      echo "<br> \$a1 \$a2 指向同一对象.";
    }else{ 
      echo "<br> \$a1 \$a2 不是一个对象.";
    }
    //$a1 的类是 A , $a2 是 A
    //$a1 $a2 指向同一对象. 
    ?>

    分享到:

    历史上的今天:

    体育大餐 2008-08-27