用户名:
密 码: 记住
您当前的位置:首页 > 网络编程 > php教程

PHP 类的变量与成员,及其继承、访问

时间:2015-01-23  来源:西部数据  作者:西部数据

基于 PHP5.3

PHP 的类及其实例,代码如下:

  1. class Myclass{ 
  2.    public $prop = 123; 
  3.  
  4. $obj = new Myclass(); 

类的成员属性(属性的称呼相对于“方法”而言)包括类常量和类变量,其中类常量在定义时不可为空,类的属性在定义时如果被赋值,只能使用标量和数组,并且不能是表达式,因为类属性在编译期被初始化,PHP 在编译期不执行表达式.

1、成员的访问控制:

public:可以继承,可以在类的方法之外被访问,如 $obj->prop;

protected:可以继承,不可以在类的方法之外被访问

private:不可以继承,不可以在类的方法之外访问

PHP 4 使用 var 来声明类的属性,在PHP5之后不再使用,PHP5.3之前使用被警告,PHP5.3之后可以用在 public 之前或单独使用作为 public 的别名.

这三个访问控制关键字也可以修饰构造函数,当 private 和 protected 修饰类的构造函数时,你只能通过一个 publice static 的静态方法来调用构造函数以实例化对象,因为够在函数无法在类之外被访问了,比如.单例类的实现,代码如下:

  1. class Singleton { 
  2.     private static $instance=null; 
  3.     public $k = 88; 
  4.     private function __construct(){ 
  5.  
  6.     } 
  7.  
  8.     public static function getInstance(){ 
  9.         if(self::$instance==null){ 
  10.                 self::$instance = new self(); 
  11.         } 
  12.  
  13.         return self::$instance
  14.     } 
  15.  
  16.     public function  __clone(){ //pretend clone oprationg 
  17.         throw('Singleton class can not be cloned'); 
  18.         return self::getInstance(); 
  19.     } 
  20. //new Singleton();  // Error 
  21. $in = Singleton::getInstance(); 

2、继承禁止:final 关键字,仅用于修饰类或类的方法

如果一个类被 final 修饰,这个类不能被继承,如果一个方法被final 修饰,则这个方法不能被子类重写(override),代码如下:

  1. class Myclass{ 
  2.   public $prop = 123; 
  3.   final public static function  methodA(){//不可继承的,公开的静态方法 
  4.         return 'this is a final method'
  5.   } 

3、抽象类和抽象方法:abstract 仅用于 类和方法,抽象类不能直接用于实例化对象只能用于产生子类,代码如下:

  1. abstract class Myclass{ 
  2.    public $prop = 123; 
  3.    abstract public function  methodA(); //抽象方法没有实现函数体 

4、类的常量及其访问,类的常量不能使用访问限制修饰符,他是 public 的,可继承,可以被子类重写,访问类的常量必须使用双冒号 ::,可以使用类名或类的实例来访问,代码如下:

  1. class Myclass{ 
  2.    public $prop = 123; 
  3.    const x =999; 
  4.   public static function methodA(){ 
  5.         return 'this is a final method'
  6.   } 
  7.   public function getConst(){ 
  8.       return self::x;  //或者 $this::x; 
  9.   } 
  10. $instance = new Myclass(); 
  11. echo Myclass::x; 
  12. echo $instance::x; 
  13. echo $instance->getConst(); 

类的常量是一个值,在代码编译期常量名被替换为相应的值,在运行期不可修改,因此,类的常量是与类本身相关,在实例化对象之前就已经存在了,因此类的常量可以直接使用类名访问,代码如下:

  1. class P{ 
  2.    const m = 100; 
  3.    const n = self::m; 
  4. class S extends P{ 
  5.   const m=200; 
  6.   public function getPConst(){ 
  7.     return parent::n; 
  8.   } 
  9. $p = new P(); 
  10. $s = new S(); 
  11. echo $p::n; //100 
  12. echo $s::n; //200 该常量名继承自父类,在编译期取 self::m 的值替换,注意区别类的方法中使用 self::m 
  13. echo $s->getPConst(); //100 

5、类的静态成员及访问

static 可 以修饰类的属性及方法,被 static 修饰的成员属于类而不属于类的实例,静态成员必须使用类名加双冒号 :: 来访问, 因为在实例化对象之前 静 态成员就存在了,因此,在静态方法内,禁止使用指向实例本身的伪变量 $this(或习惯上称为 $this 指针),可以使用关键字 self 代替 类名(相当于类的魔术常量  __CLASS__).

static 不能用于修饰 类的构造函数,也不能用于修饰接口声明的方法,代码如下:

  1. class Myclass{ 
  2.    public static $x = 99; 
  3.    public function getX(){ 
  4.    return self::$x
  5.     } 
  6. echo Myclass::x; //99 

静态成员可以使用 访问控制关键字修饰,可以被继承和重写,需要注意的是,如果一个子类继承了父类的静态方法(没有重写该方法),那么子类调用的实际是父类的静态方法,因为静态成员持有者是类不是对象,所以类的多个实例是共享同一个静态属性的,在一个实例中修改静态属性会影响到另一个实例中的静态属性,代码如下:

  1. class A{ 
  2.  
  3.    public static $a1 = 11; 
  4.  
  5.    public $a2 = 22; 
  6.  
  7.    public static function showStatic(){ 
  8.  
  9.         return  self::$a1
  10.  
  11.    } 
  12.  
  13.   public function getStatic(){ 
  14.  
  15.       return self::$a1
  16.  
  17.   } 
  18.  
  19.   public function getClassStatic(){ 
  20.  
  21.       $className = get_called_class(); 
  22.  
  23.       return  $className::$a1
  24.  
  25.   } 
  26.  
  27.   public function getProp(){ 
  28.  
  29.        return $this->a2; 
  30.  
  31.   } 
  32.  
  33.  
  34. class B extends A{    
  35.  
  36.    public static $a1 = 88; 
  37.  
  38.    public $a2 = 99; 
  39.  
  40. $obj1 = new A(); 
  41.  
  42. $obj2 = new B(); 
  43.  
  44.  
  45.  
  46. echo A::showStatic(); //11 
  47.  
  48. echo $obj1->getStatic(); //11 
  49.  
  50. echo $obj1->getClassStatic(); //11 
  51.  
  52. echo $obj1->getProp(); //22 
  53.  
  54. echo B::showStatic(); //11 调用的是父类的方法,访问父类的静态成员 
  55.  
  56. echo $obj2->getStatic(); //11 调用的是父类的方法,方法中的 self 指向持有该静态方法的类 
  57.  
  58. echo $obj2->getClassStatic(); //88 
  59.  
  60. echo $obj2->getProp(); //99 

后期静态绑定:为了避免子类重写静态属性后,使用继承来的方法仍然访问父类的静态属性,PHP5.3  增加了一个新的语法:后期静态绑定,使用 static 关键字替代 self 关键字,使得 static 指向与  get_called_class() 返回的相同的类,即当前调用该静态方法的对象所属的类,该关键字对于 静态方法的访问同样有效,代码如下:

  1. public function getClassStatic(){ 
  2.  
  3.       $className = get_called_class();  
  4.  
  5.       return  $className::$a1; 
  6.   } 
  7. //可以写成 : 
  8.   public function getClassStatic(){    
  9.       return  static::$a1; 
  10.   } 
  11. //用于静态方法,代码如下: 
  12. //A类中: 
  13.   public static function testStatic(){ 
  14.           echo "<p>testStatic of A </p>"
  15.   } 
  16.   public function callStatic(){ 
  17.        static::testStatic(); 
  18.   } 
  19.  
  20. //B类中: 
  21.     public static function testStatic(){ 
  22.           echo "<p>testStatic of B </p>"
  23.     } 
  24.  
  25. //B类继承A类的 callStatic 方法,可以正确访问各自类的 testStatic 方法。 

6、类的方法中几个指向类或实例的关键字

$this->propName   $this 指向类的实例

parent::xxx  parent 指向父类,可以访问父类的静态常量、静态属性(parent::$xxx) ,不能访问父类的非静态属性,可以调用父类的方法(不能是 private 方法,无论是否静态)

self::xxx  self 指向定义了当前被调用的方法的类,用于访问静态成员和类的常量

static::xxx 访问实例化了调用当前方法的实例的那个类,用于访问静态成员和累的常量,他跟 self 的差别是访问静态成员时采用 “后期静态绑定”.

7、类的继承中的重写问题:

重写的成员的访问控制程度不能被缩小,例如,public 的成员不能重写为 protected,非静态成员不能重写为静态成员,静态成员也不能重写为非静态成员.

8、接口中定义的方法必须是 public

类在实现接口的方法时,这些方法也必须是 public 的,具体实现的(不能是 abstract ),接口也可以定义接口常量,用法与类常量完全一致,但是接口不可以定义非函数成员.

接口与接口之间可以继承,接口的继承可以是多继承,用逗号隔开(字类与父类的继承是单继承的),一个类可以实现多个接口,用逗号隔开,代码如下:

  1. interface Ix extends Iy,Iz{ 
  2.    public function a(); 
  3. class A implements Iy,Iz{ 
  4.    ....... 

9、类型约束

PHP 的函数(或类的方法)可以在声明时限定参数的类型,但只能 限定 array 或 object(class/interface),如果限定为 string 型,PHP 会认为是限定为一个 string 类 的 object 参数,如果类型被限定为某个接口,则传入的参数必须是实现该接口的类的实例.

在接口实现、子类重写父类方法时,不能修改已经限定的参数类型,在方法、函数调用时,如果传入了与限定的参数类型不同的数据将会报错,但是可以接受  null 参数,代码如下:

  1. interface Im{ 
  2.    public function a( classm $m); 
  3. class A implements Im{ 
  4.     public function a($x){   // error ,参数$x必须限定为 classm 类型以匹配接口的定义 
  5.        var_dump($x); 
  6.     } 
来顶一下
返回首页
返回首页
推荐资讯
WiFi太不安全:7岁女孩11分钟内入侵公共网络 WiFi太不安全:7岁女孩11分钟内入侵近期刚刚发布研究说WiFi网络能获得人们手机里多少私人信息,
不服跑个分?人工智能也出现“刷分”乱象 不服跑个分?人工智能也出现“刷分2014年,人工智能领域突然爆发,成为了科研和科技创业的热门
相关文章
    无相关信息
栏目更新
栏目热门