设为首页 收藏本站
查看: 585|回复: 0

[经验分享] PHP 类的变量与成员,及其继承、访问与重写要注意的问题

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2015-8-29 10:59:44 | 显示全部楼层 |阅读模式
  基于 PHP5.3
  PHP 的类及其实例:



class Myclass{
public $prop = 123;
}
$obj = new Myclass();
  
  类的成员属性(属性的称呼相对于“方法”而言)包括类常量和类变量,其中类常量在定义时不可为空,类的属性在定义时如果被赋值,只能使用标量和数组,并且不能是表达式,因为类属性在编译期被初始化,PHP 在编译期不执行表达式。
  
  1、成员的访问控制:
  public:可以继承,可以在类的方法之外被访问 , 如 $obj->prop;
  protected:可以继承,不可以在类的方法之外被访问
  private:不可以继承,不可以在类的方法之外访问
  
  PHP 4 使用 var 来声明类的属性,在PHP5之后不再使用,PHP5.3之前使用被警告,PHP5.3之后可以用在 public 之前或单独使用作为 public 的别名。
  这三个访问控制关键字也可以修饰构造函数,当 private 和 protected 修饰类的构造函数时,你只能通过一个 publice static 的静态方法来调用构造函数以实例化对象,因为该函数无法在类之外被访问了,比如,单例类的实现:



class Singleton {
private static $instance=null;
public $k = 88;
private function __construct(){
}
public static function getInstance(){
if(self::$instance==null){
self::$instance = new self();
}
return self::$instance;
}
public function  __clone(){ //pretend clone oprationg
throw('Singleton class can not be cloned');
return self::getInstance();
}
}
//new Singleton();  // Error
$in = Singleton::getInstance();  
  
  
  2、继承禁止: final 关键字,仅用于修饰类或类的方法
  如果一个类被 final 修饰,这个类不能被继承,如果一个方法被final 修饰,则这个方法不能被子类重写(override)。



class Myclass{
public $prop = 123;
final public static function  methodA(){//不可继承的,公开的静态方法
return 'this is a final method';
}
}
  
  3、抽象类和抽象方法:abstract 仅用于 类和方法,抽象类不能直接用于实例化对象只能用于产生子类



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

}
  
  4、类的常量及其访问:类的常量不能使用访问限制修饰符,他是 public 的,可继承,可以被子类重写,访问类的常量必须使用双冒号 :: ,可以使用类名或类的实例来访问,因为是常量,所以名称不能使用表示变量的符号 $ 。



class Myclass{
public $prop = 123;
const x =999;
public static function methodA(){
return 'this is a final method';
}
public function getConst(){
return self::x;  //或者 $this::x;

}
}
$instance = new Myclass();

echo Myclass::x;
echo $instance::x;
echo $instance->getConst();
  
  类的常量是一个值,在代码编译期常量名被替换为相应的值,在运行期不可修改,因此,类的常量是与类本身相关,在实例化对象之前就已经存在了,因此类的常量可以直接使用类名访问。



class P{
const m = 100;
const n = self::m;
static $k = 99;
public function getStatic(){
return self::$k;
}
public function getStatic2(){
return static::$k;
}
}

class S extends P{
const m=200;
static $k = 88;
public function getPConst(){
return parent::n;
}
}

$p = new P();
$s = new S();
echo $p::n; //100
echo '<br />';
echo $s::n; //200 该常量名继承自父类,在编译期就已经直接取 self::m 的值替换了 ,注意区别类的方法中使用 self::m
echo '<br />';
echo $s->getPConst(); //100
echo '<br />';
echo $s->getStatic(); //99 调用方法时
echo '<br />';
echo $s->getStatic2(); //111
  
  5、类的静态成员及访问
  static 可 以修饰类的属性及方法,被 static 修饰的成员归属于类而非类的实例,静态成员必须使用类名加双冒号 :: 来访问, 因为在实例化对象之前 静 态成员就存在了,因此,在静态方法内,禁止使用指向实例本身的伪变量 $this(或习惯上称为 $this 指针) ,可以使用关键字 self 代替 类名(相当于类的魔术常量  __CLASS__)。
  static 不能用于修饰 类的构造函数,也不能用于修饰接口声明的方法。
  



class Myclass{
public static $x = 99;
public function getX(){
return self::$x;
}
}
echo Myclass::x; //99
  
  
  静态成员可以使用 访问控制关键字修饰,可以被继承和重写,需要注意的是,如果一个子类继承了父类的静态方法(没有重写该方法),那么子类调用的实际是父类的静态方法。因为静态成员持有者是类不是对象,所以类的多个实例是共享同一个静态属性的,在一个实例中修改静态属性会影响到另一个实例中的静态属性:



class A{
public static $a1 = 11;
public $a2 = 22;
public static function showStatic(){
return  self::$a1;
}

public function getStatic(){
return self::$a1;
}

public function getClassStatic(){
$className = get_called_class();
return  $className::$a1;
}


public function getProp(){
return $this->a2;
}

}

class B extends A{   
public static $a1 = 88;
public $a2 = 99;
}

$obj1 = new A();
$obj2 = new B();

echo A::showStatic(); //11
echo $obj1->getStatic(); //11
echo $obj1->getClassStatic(); //11
echo $obj1->getProp(); //22

echo B::showStatic(); //11 调用的是父类的方法,访问父类的静态成员
echo $obj2->getStatic(); //11 调用的是父类的方法,方法中的 self 指向持有该静态方法的类
echo $obj2->getClassStatic(); //88
echo $obj2->getProp(); //99
  
  后期静态绑定:为了避免子类重写静态属性后,使用继承来的方法仍然访问父类的静态属性, PHP5.3  增加了一个新的语法:后期静态绑定,使用 static 关键字替代 self 关键字,使得 static 指向与  get_called_class() 返回的相同的类,即当前调用该静态方法的对象所属的类,该关键字对于 静态方法的访问同样有效。
  



  public function getClassStatic(){
$className = get_called_class();  
return  $className::$a1;
}

//可以写成 :

public function getClassStatic(){   
return  static::$a1;
}

//用于静态方法
//A类中:
public static function testStatic(){
echo "<p>testStatic of A </p>";
}
public function callStatic(){
static::testStatic();
}

//B类中:
public static function testStatic(){
echo "<p>testStatic of B </p>";
}

//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 )。
  接口也可以定义接口常量,用法与类常量完全一致,但是接口不可以定义非函数成员。
  接口与接口之间可以继承,接口的继承可以是多继承,用逗号隔开(字类与父类的继承是单继承的)
  一个类可以实现多个接口,用逗号隔开



interface Ix extends Iy,Iz{
public function a();
}

class A implements Iy,Iz{
.......
}
  
  9、类型约束
  PHP 的函数(或类的方法) 可以在声明时限定参数的类型,但只能 限定 array 或 object(class/interface) ,如果限定为 string 型, PHP 会认为是限定为一个 string 类 的 object 参数。
  如果类型被限定为某个接口,则传入的参数必须是实现该接口的类的实例。
  在接口实现、子类重写父类方法时,不能修改已经限定的参数类型。
  在方法、函数调用时,如果传入了与限定的参数类型不同的数据将会报错,但是可以接受  null 参数。
  



interface Im{
public function a( classm $m);
}

class A implements Im{
public function a($x){   // error ,参数$x必须限定为 classm 类型以匹配接口的定义
var_dump($x);
}
}
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-105850-1-1.html 上篇帖子: phpcms model.class.php分析 下篇帖子: PHP弹出确认框
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

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