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的静态方法调用构造函数以实例化对象,因为该构造函数无法在类之外被访问了,比如,单例类的实现:
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)。
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;
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;
?>
类的常量是一个值,在代码编译器常量名被替换为相应的值,在运行期不可修改,因此类的常量与类本身无关,在类实例化对象之前就已经存在,因此类的常量可以直接使用类名访问。
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>';//100
echo $s::N.'<br>';//200 该常量名继承自父类,在编译期就已经直接取 self::M 的值替换了 ,注意区别类的方法中使用 self::M
echo $s->getPConst().'<br>';//100
echo $s->getStatic2().'<br>';//88
?>
5、类的静态成员访问
static可以修饰类的属性和方法,被static修饰的成员归属于类而非类的实例。静态成员必须使用类名加双冒号::来访问,因此在实例化对象之前静态成员就存在了,因此,在静态方法内禁止使用指向实例本身的伪变量$this(或习惯上称为$this指针),可以使用关键字self代替类名(相当于类的魔术常量__CLASS__)。
static不能修饰类的构造函数,也不能修饰接口声明的方法。
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>";
?>
静态成员可以使用访问控制关键字修饰,可以被继承和重写,需要注意的是,如果一个子类继承了父类的静态方法(没有重写该方法),那么子类调用的实际是父类的静态方法。因为静态成员持有者是类不是对象,所以类的多个实例是共享一个静态属性,在一个实例中修改静态属性会影响到另一个实例的静态属性:
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>";//11
echo $obj1->getClassStatic()."<br>";//11
echo $obj1->getProp()."<br>";//22
echo B::showStatic()."<br>";//11调用的是父类的方法,访问父类的静态成员
echo $obj2->getStatic()."<br>";//调用的是父类的方法,方法中的slef指向持有该静态方法的类
echo $obj2->getClassStatic()."<br>";//88
echo $obj2->getProp()."<br>";//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;
}
6、类的方法中几个指向类或实例的关键字
$this->propName $this指向类的实例
parent::xxx parent指向父类,可以访问父类的静态常量、静态属性,不能访问父类的非静态属性,可以调用父类的方法(不能是private方法,无论是否静态)
self::xxx self指向定义了当前被调用的方法的类,用于访问静态成员和类的常量
static::xxx 访问实例化了调用当前方法的实例的那个类,用于访问静态成员和类的常量,它跟self的差别是访问静态成员是“后期静态绑定”
7、类的继承中的重写问题
重写的成员的访问控制程度不能被缩小,例如,public的成员不能重写为protected
非静态成员不能重写为静态成员,静态成员也不能重写为非静态成员
8、接口中定义的方法必须是public
类在实现接口的方法时,这些方法也必须是public的。
接口也可以定义接口常量,用法和类的常量一致,但是接口不可以定义非函数成员。
接口与接口之间可以继承,接口的继承可以是多继承,用逗号隔开(子类与父类的继承是单继承)。
一个口可以实现多个接口,用逗号隔开。
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);
}
}
?>
来源:https://www.cnblogs.com/zhouguowei/p/5209728.html