一个类可以包含有属于自己的常量,变量(称为“属性”)以及函数(称为“方法”)。当一个方法在类定义内部被调用时,有一个可用的伪变量 $this。$this 是一个到主叫对象的引用,通常是该方法所从属的对象。
一个类可以在声明中用 extends 关键字继承另一个类的方法和属性。PHP不支持多重继承,一个类只能继承一个基类。
被继承的方法和属性可以通过用同样的名字重新声明被覆盖。但是如果父类定义方法时使用了 final,则该方法不可被覆盖。可以通过 parent:: 来访问被覆盖的方法或属性。
当覆盖方法时,参数必须保持一致否则 PHP 将发出 E_STRICT 级别的错误信息。但构造函数例外,构造函数可在被覆盖时使用不同的参数。
引用和赋值
对象拥有很多的属性和方法,这些基本类型的数据在自己的坑好好呆着,一个对象的句柄也作为一种基本类型在一个坑呆着。当$objectVar的引用赋给$reference时,这两个对象的句柄都指向同一个坑,它们的foo也是指向同一个坑,但是把$objectVar作为一个变量赋给$assignment时,它们的handle指向同一个坑,但是这个时候坑的引用计数变成2。
self 和 $this 区别:self指的是当前类,$this指当前对象
stdClass: 是php的默认对象,不包含任何属性、方法,不支持魔术方法,不实现任何接口,它不是基本类型。
类的常量
常量的值必须是一个定值,不能是变量,类属性,数学运算的结果或函数调用。
在父类定义了常量,在子类可以被覆盖。
需要注意的:在类中定义了一个常量,用self::$name和static::$name都获取不到,前一个是undefined,后一个是null。只能用类名获取。
自动加载类
可以定义一个 __autoload() 函数,它会在试图使用尚未被定义的类时自动调用。
spl_autoload_register方法:定义一个方法load加载某个文件,spl_autoload_register(‘load’),表示在遇到没有定义的类的时候就执行load方法自动加载。
spl_autoload_register( array('test','loadprint') );表示加载test类的loadprint方法
构造函数和析构函数
如果子类中定义了构造函数则不会隐式调用其父类的构造函数。要执行父类的构造函数,需要在子类的构造函数中调用 parent::__construct()。如果子类没有定义构造函数则会如同一个普通的类方法一样从父类继承(假如没有被定义为 private 的话)。
和构造函数一样,父类的析构函数不会被引擎暗中调用。要执行父类的析构函数,必须在子类的析构函数体中显式调用 parent::__destruct()。此外也和构造函数一样,子类如果自己没有定义析构函数则会继承父类的。
析构函数即使在使用 exit() 终止脚本运行时也会被调用。在析构函数中调用 exit() 将会中止其余关闭操作的运行。
访问控制
属性:public,var供有,private,私有,protected 受保护
方法:不写任何定义,则默认共有。
同一个类的对象即使不是同一个实例也可以互相访问对方的私有与受保护成员。这是由于在这些对象的内部具体实现的细节都是已知的。
如果一个类被定义成abstract,它就必须被继承,不能直接使用。
静态常量
static类型的属性在子类定义,父类可以访问。self和static:self指的是当前类的,就是代码所在的那个类,static指定的调用它的类。
抽象类
定义为抽象的类不能被实例化。任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。
继承一个抽象类的时候,子类必须定义父类中的所有抽象方法;另外,这些方法的访问控制必须和父类中一样(或者更为宽松)。例如某个抽象方法被声明为受保护的,那么子类中实现的方法就应该声明为受保护的或者公有的,而不能定义为私有的。此外方法的调用方式必须匹配,即类型和所需参数数量必须一致。例如,子类定义了一个可选参数,而父类抽象方法的声明里没有,则两者的声明并无冲突。
trait代码复用:优先级:当前类的成员>trait>从基类继承的成员。同时使用多个trait时,如果有同名方法:需要用insteadof 解决冲突。
trait可以定义属性
重载
这些魔术方法的参数都不能通过引用传递。
属性重载
public void __set ( string $name , mixed $value )
public mixed __get ( string $name )
public bool __isset ( string $name )
public void __unset ( string $name )
在给不可访问属性赋值时,__set() 会被调用,前提是在类中定义了__set()方法,否则会报错,下面几种场景类似。
读取不可访问属性的值时,__get() 会被调用。
当对不可访问属性调用 isset() 或 empty() 时,__isset() 会被调用。
当对不可访问属性调用 unset() 时,__unset() 会被调用。
参数 $name 是指要操作的变量名称。__set() 方法的 $value 参数指定了 $name 变量的值。
属性重载只能在对象中进行。在静态方法中,这些魔术方法将不会被调用。所以这些方法都不能被 声明为 static。
方法重载
public mixed __call ( string $name , array $arguments )
public static mixed __callStatic ( string $name , array $arguments )
在对象中调用一个不可访问方法时,__call() 会被调用。前提是在类中定义了__callStatic()方法,否则会报错,下面的__callStatic() 类似。
用静态方式中调用一个不可访问方法时,__callStatic() 会被调用。
对象遍历
foreach可以遍历对象的可见属性。
在类的内部用$this可以遍历所有属性。
魔术方法
PHP 将所有以 __(两个下划线)开头的类方法保留为魔术方法。
serialize() 函数会检查类中是否存在一个魔术方法__sleep()。如果存在,该方法会先被调用,然后才执行序列化操作。此功能可以用于清理对象,并返回一个包含对象中所有应被序列化的变量名称的数组。如果该方法未返回任何内容,则 NULL 被序列化,并产生一个 E_NOTICE 级别的错误。
__sleep() 不能返回父类的私有成员的名字。这样做会产生一个 E_NOTICE 级别的错误。可以用 Serializable 接口来替代。
__sleep() 方法常用于提交未提交的数据,或类似的清理操作。同时,如果有一些很大的对象,但不需要全部保存,这个功能就很好用。
与之相反,unserialize() 会检查是否存在一个 __wakeup() 方法。如果存在,则会先调用 __wakeup 方法,预先准备对象需要的资源。
__wakeup() 经常用在反序列化操作中,例如重新建立数据库连接,或执行其它初始化操作。
当尝试以调用函数的方式调用一个对象时,__invoke() 方法会被自动调用。
如果父类中的方法被声明为 final,则子类无法覆盖该方法。如果一个类被声明为 final,则不能被继承。
对象比较
当使用比较运算符(==)比较两个对象变量时,比较的原则是:如果两个对象的属性和属性值 都相等,而且两个对象是同一个类的实例,那么这两个对象变量相等。
而如果使用全等运算符(===),这两个对象变量一定要指向某个类的同一个实例(即同一个对象)。
类型约束
在方法的参数前加上参数类型,表示所需要的参数类型,如果传的参数不是这个类型,会抛错误。
后期静态绑定
static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。也可以称之为“静态绑定”,因为它可以用于(但不限于)静态方法的调用。栗子:
<pre>
<?php
class A {
public static function who() {
echo __CLASS__;
}
public static function test() {
static::who(); // 后期静态绑定从这里开始,如果这行代码变成
self::who();B:test()输出A
}
}
class B extends A {
public static function who() {
echo __CLASS__;
}
}
B::test(); //输出B
?>
</pre>
网友评论