PHP类的变量与成员,及其继承、访问与重写要注意的问题
PHP的类及其实例:
<?php
class Myclass{
public $prop = 123;
}
$obj = new Myclass();
?>
类的成员属性(属性的称呼相对于‘方法’而言)包括类常量和类变量,其中类常量在定义时不可为空,类的属性在定义时如果被赋值,只能使用变量和数组,并且不能是表达式,因为类属性在编译期被初始化,PHP在编译器不执行表达式。
1、成员的访问控制
public:可以继承,可以在类的方法之外被访问,如$obj->prop;
protected:可以继承,不可以在类的方法之外被访问;
private:不可以继承,不可以在类的方法之外访问;
PHP4使用var来声明类的属性,在PHP5之后不再使用,PHP5.3之前使用被警告,在PHP5.3之后可以在public之前或单独使用作为public的别名。
这三个访问控制关键字也可以修饰构造函数,当private和protected修饰类的构造函数时,只能通过一个public static的静态方法调用构造函数以实例化对象,因为该构造函数无法在类之外被访问了,比如,单例类的实现:
<?php
class Singleton{
private static $instance = null;
public $k = 88;
private function __construct(){
}
public static function getInstance(){
if(self::$instance == null){
//self::$instance = new Singleton();
self::$instance = new self();
}
return self::$instance;
}
public function __clone(){
throw new Exception('Singleton class can not be cloned');
return self::$instance;
}
}
//$in = new Singleton();
$in = Singleton::getInstance();
var_dump($in);
?>
2、继承禁止:final关键字,仅用于修饰类或类的方法
如果一个类被final修饰,这个类不能被继承,如果一个方法被final修饰,则这个方法不能被子类重写(override)。
<?php
class Myclass{
public $prop = 123;
final public static function methodA(){
return 'this is a final method';
}
}
?>
3、抽象类和抽象方法,abstract仅用于类和方法,抽象类不能直接用于实例化对象,只能用于产生子类
<?php
abstract class Myclass{
public $prop = 123;
abstract public function methodA();//抽象方法没有实现函数体
}
?>
4、类的常量及其访问:类的常量不能使用访问控制修饰符,他是public的,可继承,可以被子类重写。访问类的常量必须使用双冒号::,可以使用类名或类的实例(对象)来访问,因为是常量,所以名称不能使用表示变量的符号$。
<?php
class Myclass{
public $prop = 123;
const X = 999;
final public static function methodA(){
return 'this is a final method';
}
public function getConst(){
return self::X;//或者$this::X
}
}
$in = new Myclass();
echo $in->getConst();
echo Myclass::X;
?>
类的常量是一个值,在代码编译器常量名被替换为相应的值,在运行期不可修改,因此类的常量与类本身无关,在类实例化对象之前就已经存在,因此类的常量可以直接使用类名访问。
<?php
class P{
const M = 100;
const N = self::M;
public static $k = 99;
public function getStatic(){
return self::$k;
}
public function getStatic2(){
return static::$k;
}
}
class S extends P{
const M = 200;
public static $k = 88;
public function getPConst(){
return parent::N;
}
}
$p = new P();
$s = new S();
echo $p::N.'<br>';//
echo $s::N.'<br>';//200 该常量名继承自父类,在编译期就已经直接取 self::M 的值替换了 ,注意区别类的方法中使用 self::M
echo $s->getPConst().'<br>';//
echo $s->getStatic2().'<br>';//
?>
5、类的静态成员访问
static可以修饰类的属性和方法,被static修饰的成员归属于类而非类的实例。静态成员必须使用类名加双冒号::来访问,因此在实例化对象之前静态成员就存在了,因此,在静态方法内禁止使用指向实例本身的伪变量$this(或习惯上称为$this指针),可以使用关键字self代替类名(相当于类的魔术常量__CLASS__)。
static不能修饰类的构造函数,也不能修饰接口声明的方法。
<?php
class Myclass{
public static $x = 99;
public function getX(){
return self::$x;
}
public static function getX2(){
return self::$x;
}
}
echo Myclass::$x."<br>";
echo Myclass::getX2()."<br>";
$MC = new Myclass();
echo $MC->getX2()."<br>";
?>
静态成员可以使用访问控制关键字修饰,可以被继承和重写,需要注意的是,如果一个子类继承了父类的静态方法(没有重写该方法),那么子类调用的实际是父类的静态方法。因为静态成员持有者是类不是对象,所以类的多个实例是共享一个静态属性,在一个实例中修改静态属性会影响到另一个实例的静态属性:
<?php
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 $obj1->getStatic()."<br>";//
echo $obj1->getClassStatic()."<br>";//
echo $obj1->getProp()."<br>";//
echo B::showStatic()."<br>";//11调用的是父类的方法,访问父类的静态成员
echo $obj2->getStatic()."<br>";//调用的是父类的方法,方法中的slef指向持有该静态方法的类
echo $obj2->getClassStatic()."<br>";//
echo $obj2->getProp()."<br>";//
?>
后期静态绑定:为了避免子类重写静态属性后,使用继承来的方法仍然方法父类的静态属性,PHP5.3增加了一个新的语法,后期静态绑定,使用static关键词替代self关键字,使得static指向与get_called_class()返回的相同类,即当前调用该静态方法的对象所属的类,该关键字对于静态方法的访问同样有效。
public function getClassStatic(){
$className = get_called_class();
return $className::$a1;
}
//可以写成
public function getClassStatic(){
return static::$a1;
}
6、类的方法中几个指向类或实例的关键字
$this->propName $this指向类的实例
parent::xxx parent指向父类,可以访问父类的静态常量、静态属性,不能访问父类的非静态属性,可以调用父类的方法(不能是private方法,无论是否静态)
self::xxx self指向定义了当前被调用的方法的类,用于访问静态成员和类的常量
static::xxx 访问实例化了调用当前方法的实例的那个类,用于访问静态成员和类的常量,它跟self的差别是访问静态成员是“后期静态绑定”
7、类的继承中的重写问题
重写的成员的访问控制程度不能被缩小,例如,public的成员不能重写为protected
非静态成员不能重写为静态成员,静态成员也不能重写为非静态成员
8、接口中定义的方法必须是public
类在实现接口的方法时,这些方法也必须是public的。
接口也可以定义接口常量,用法和类的常量一致,但是接口不可以定义非函数成员。
接口与接口之间可以继承,接口的继承可以是多继承,用逗号隔开(子类与父类的继承是单继承)。
一个口可以实现多个接口,用逗号隔开。
<?php
interface Ix extends Iy,Iz{
public function a();
}
class A implements Iy,Iz{
//.......
}
?>
9、类型约束
PHP的函数(或类的方法)可以在声明是限定参数的类型,但只能限定array或object(class/interface),如果限定为string,PHP会认为是限定为一个string类的object参数。
如果类型被限定为某一个接口,则传入的参数必须是实现该接口的类的实例。
在接口实现、子类重写父类方法时,不能修改已经限定的参数类型。
在方法、函数调用时,如果传入了与限定的参数类型不同的数据将会报错,但是可以接收null参数。
<?php
interface Im{
public function a( classm $m);
}
class A implements Im{
public function a($x){ // error ,参数$x必须限定为 classm 类型以匹配接口的定义
var_dump($x);
}
}
?>
PHP类的变量与成员,及其继承、访问与重写要注意的问题的更多相关文章
- Swift学习——类的定义,使用,继承,构造等(五)
Swift学习--类的定义,使用.继承,构造等(五) 类的使用说明 1 使用class和类名来创建一个类名,比如: class student 2 类中属性的声明和常量和变量一样,唯一的差别就是他们的 ...
- Effective Java:Ch4_Class:Item13_最小化类及其成员的可访问性
要区别一个模块是否设计良好,最重要的因素是,对于其他模块而言该模块隐藏其内部数据和其他实现细节的程度.设计良好的模块应该隐藏所有实现细节,将API与其实现清晰地隔离开来.这样,模块之间通过他们的API ...
- 《Effective Java》笔记 使类和成员的可访问性最小化
类和接口 第13条 使类和成员的可访问性最小化 1.设计良好的模块会隐藏所有的实现细节,把它的API与实现清晰的隔离开来,模块之间只通过它们的API进行通信,一个模块不需要知道其他模块的内部工作情况: ...
- Effective Java 第三版——15. 使类和成员的可访问性最小化
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- java中的类修饰符、成员变量修饰符、方法修饰符。
类修饰符: public(访问控制符),将一个类声明为公共类,他可以被任何对象访问,一个程序的主类必须是公共类. abstract,将一个类声明为抽象类,没有实现的方法,需要子类提供方法实现. fin ...
- java中的类修饰符、成员变量修饰符、方法修饰符
类修饰符: public(访问控制符),将一个类声明为公共类,他可以被任何对象访问,一个程序的主类必须是公共类. abstract,将一个类声明为抽象类,没有实现的方法,需要子类提供方法实现. fi ...
- Java:【面向对象:类的定义,静态变量,成员变量,构造函数,封装与私有,this】
本文内容: 什么是面对对象 类的定义与对象实例化 成员变量 成员变量的有效范围 成员变量的赋值 静态变量.方法与实例变量.方法 构造函数 封装与私有 this关键字 注:函数和方法是一样东西.[由于我 ...
- 类的static成员变量和成员函数能被继承吗
1. 父类的static变量和函数在派生类中依然可用,但是受访问性控制(比如,父类的private域中的就不可访问),而且对static变量来说,派生类和父类中的static变量是共用空间的,这点 ...
- Java第11次作业:什么是继承?继承的好处?什么是覆写?super()?构造代码块?子父类初始化顺序? 抽象类能用final声明吗?final关键字声明类 方法 变量以及全局常量?抽象类的构造方法?
什么是继承? 继承是以父类为基础,子类可以增加新的数据或新的功能.子类不能选择性地继承父类.这种技术使得复用以前的代码非常容易. JAVA不支持多继承,单继承使JAVA的继承关系很简单,一个类只能有一 ...
随机推荐
- A Survey of Shape Feature Extraction Techniques中文翻译
Yang, Mingqiang, Kidiyo Kpalma, and Joseph Ronsin. "A survey of shape feature extraction techni ...
- virtualenv使用说明
创建虚拟环境virtualenv [虚拟环境名称] 如:virtualenv ENV 启动虚拟环境 cd ENV source ./bin/activate 注意此时命令行会多一个(ENV),ENV为 ...
- JS异步笔记
Promise 最早接触异步是在.net中,当时还是比较流行使用基于控件的BackgroundWorker,其自身通过子线程的方式来异步处理一些情况,并且封装了一些功能与主线程通信.后来,开始使用Th ...
- 百度网盘不能绑定QQ
一定要等!!!进度条!! 等全部加载完再点就可以了. 不然的话点关联账号的话会直接跳回个人信息页面. over. 百度账号(百度网盘)绑定QQ账号的页面为什么打不开 总会跳转到个人信息界面,和没点一样 ...
- 制作dos启动u盘
需要准备的工具: 空U盘的U盘HP优盘启动盘格式化工具 链接:https://pan.baidu.com/s/1i59wgUp 密码:l5ke 1.1插入U盘,打开 HP优盘启动盘格式化工具 1. ...
- IIS配置(持续更新中...)
本文暂时适用于IIS7.5. IIS配置文件路径:"C:\Windows\System32\inetsrv\config\applicationHost.config" 1.sta ...
- Linux I/O 进阶
非阻塞I/O 阻塞I/O对应于低速的系统调用,可能会使进程永远阻塞.非阻塞I/O可以使我们发出open.read.write这样的I/O操作,并使这些操作不会永远阻塞.如果这种操作不能完成,则调用立即 ...
- EasyNVR和EasyDSS云平台联手都不能解决的事情,只有国标GB28181能解决了
需求痛点 我们经常收到这样一种需求,就是将客户手里的各种类型的网络摄像机IPC和网络硬盘录像机NVR进行统一的整合接入和管理,并进行常规的直播.存储.录像检索和回放等操作,而这个时候我们通常会选择用E ...
- VS2010程序崩溃- APPCRASH
使用VS2010打开某个项目出现错误,程序崩溃:还不是全部的项目:开始以为是那个项目本身有什么问题,查了很久发现不是这样的 程序崩溃提示 问题签名: 问题事件名称: APPCRASH 应用程序名: d ...
- php cmd 不能利用$_COOKIE 的处理 通过文件来暂存字符串
路径 <?php define('CMDPATH', 'wD:\cmd\\'); echo CMDPATH; die(); broswer 路径无问题 w 读 用 <?php $wfile ...