对象是放在“堆内存”里面, 对象的引用被放到了“栈内存”里,而静态成员则放到了“初始化静态段”
自动加载类
__autoload(){}
会在使用尚未被定义的类的时候自动调用此函数,autoload函数接收一个参数,即需要引入的类名。
function __autoload($className){
require_once $className.".php";
}
$obj=new MyClass(); //MyClass类不存在自动调用函数__autoload(),在实例化类的时候写__autoload()函数。此实例化时会传入参数“MyClass”。
此时不必将所需引入的类都一一 include进来。
对象串行化
串行化:serialize(); 当某些对象需要在网络上传输,为了传输方便,可以将对象转为二进制串,当到达另一端时,再还原为原来的对象。
反串行化:unserialize(); 把对象的二进制串再转为对象。
$p1=new Person('张三','男','20');
$p1_string=serialize($p1);
echo $p1_strubg;
$p2=unserialize($p1_string);
魔术方法:
__sleep():在串行化之前做一些操作(该方法不接受参数,但返回一个数组)
__wakeup():由二进制串重新组成新对象时,做一些对象醒来做的事。
function __sleep(){
$arr=new array('name','sex'); //数组里是需要进行串行化的属性名
return $arr;
}
function __wakeup(){
$this->age='36';
}
接口interface
作用:让子类遵守父类接口的规范。指定了一个实现了该接口的类必须实现的一系列 方法。
如果一个抽象类里面的所有的方法都是抽象方法,那么我们就换一 种声明方法使用“接口”。接口里的方法都是抽象方法,可以省略abstract关键字,默认都是抽象方法。接口中方法是空方法。
接口里不能声明变量,只能声明常量(const )。
接口里所有的成员都是public权限的,也可省略不写,默认public。
接口是特殊的抽象类,里面所有的方法都是抽象方法,不能产生实例化对象,所有抽象方法需要子类去实现。
子类实现接口中的抽象方法用implements,接口继承接口使用extends。
抽象方法
使用abstract关键字修饰,没有方法体,abstract function fun1();
抽象类
只要类里有一个方法是抽象方法,这个类就要定义为抽象类,使用abstract关键字。
抽象类不能被实例化,只能被继承。
子类继承父类,子类必须实现父类全部的抽象方法,否则等于子类中包含抽象方法,子类也不能被实例化。
再通过实例化子类实现抽象的方法。
__call 处理调用错误
当调用的方法名错误或不存在调用的方法时,将执行该函数。
第一个参数:调用错误的方法名;
第二个参数:调用错误的方法时传的参数,以数组的形式传过来。
class Person{
function __call($errFunName,$arrs){
print('您调用的方法:'.$errFunName."(参数为:");
print_r($arrs);
print(')错误或不存在!');
}
}
$p1=new Person();
$p1->run('1min','500m');
echo "Hello"; //当不存在__call方法时,如果调用不存在的方法,不会执行到此句。
克隆对象 clone
根据一个对象克隆出另一个一样的对象,克隆后两个对象互不干扰。
$p1=new Person('李木子','20','女');
$p2=clone $p1;
//使用clone克隆新对象p2,和p1对象具有相同的属性和方法。
在对象克隆时会自动调用"__clone"方法,该方法可以建立一个与原对象拥有相同属性和方法的对象。若想在克隆后改变原对象的内容,可以重写此方法。
"__clone"方法包含两个指针:$this指向复本,$that指向原本。
class Person{
...
function say(){
echo "我叫:".$this->name.",今年".$this->age."岁";
}
function __clone(){
$this->name="我是假的".$that->name;
$this->age='100';
}
}
$p1=new Person('张三','20','男');
$p2=clone $p1;
$p1->say();
$p2->say();
__toString() 输出对象引用时自动调用
$p1=new Person(); 此时$p1就是一个引用,此时如果输出“echo $p1;”会出错。
function __toString(){
echo "您输出的是个引用";
}
static
静态成员属于类,在类第一次被加载的时候分配的空间,其他类无法访问,只对类的实例共享。使用对象访问不到静态成员的。
从内存角度:对象是在堆内存中,对象的引用放在栈内存中。静态成员放在“初始化静态段”,在类第一次被加载的时候放入的,可以让堆内存里面的每个对象所共享。
访问静态方法:类名::方法名();
访问静态属性:类名::$属性名;
或使用”self ::$attr;“。
self 是代表这个静态方法所在的类。
self表示当前类,即使该类类名被修改,仍可使用。
self是在类内调用静态成员的方式,而类名在类内和类外都可以调用。
一般来说,对象调用非静态方法,类用来调用静态方法。
类里的静态方法只能访问静态属性(想在本类的方法中想访问本类的其他成员,需要使用$this这个引用,而静态方法不用对象调用的,而是使用类名来访问的 ,所以没有对象的存在,也就没有$this这个引用)
非静态方法可以访问静态属性,通过“self::成员属性名”
静态访问修饰符 “::”
const定义常量
也可使用define()函数
访问常量时通过类名,在方法里通过self,但是不使用$符号,也不能使用对象来访问。
访问:
类名::常量名(不加$符号)
self::常量名(不加$符号)
final关键字
使用final关键字标记的类不能被继承。
使用final关键字标记的方法不能被子类覆盖。
三种访问修饰符
public(公有的,默认的),private(私有的),protected(受保护的)
private | protected | public | |
同一个类中 | ok | ok | ok |
类的子类中 | ok | ok | |
所有的外部成员 | ok |
方法重载
方法名相同,参数个数和参数类型不同
方法覆盖
子类继承父类,通过重写父类相同的方法名实现覆盖,重写父类的方法
想在父类方法的基础上进行扩展:
调用父类被覆盖的方法:
parent::方法名();
类名::方法名();
class children extends Person{
...
function say(){
//Person::say();
parent::say();
echo "在这可以加点功能";
}
}
__set()
用来为私有成员属性设置值。有两个参数,第一个参数为设置的属性名,第二个参数为设置的属性值。
function __set($property_name,$value){
$this->$proprty_name=$value;
}
__get()
用来获取私有成员属性的值。
function __get($property_name){
if(isset($property_name)){
return $property_name;
}else{
return NULL;
}
}
isset()
传入一个变量作为参数,如果存在返回true,不存在返回false。
unset()
传入一个变量,删除指定的变量。
构造函数__construct()
或是和类名相同的方法名,也是构造函数。如类名为a,则方法名为a的是构造函数。
使用new关键字来实例化对象的时候会自动调用构造方法,可以做一些初始化的工作,如为成员属性赋初值。
析构函数__destruct()
在销毁一个类之前执行一些操作。
$this
本对象的引用
$this->属性
$this->方法
使用对象的成员
对象成员包括成员属性和成员方法。通过“->”操作符访问
对象->属性
对象->方法
实例化对象
$对象名称 = new 类名称();
内存从逻辑上分为四段
栈空间段,堆空间段,代码段,初始化静态段
类
类是具有相同属性和服务的一组对象的集合。关键字class。
类和对象的关系
类与对象的关系就如磨具和铸件的关系。对象是类的实例化,类是对象的抽象。类是对某一类事物的抽象描述,对象用于表示现实中该类事物的个体,类用于描述多个对象的共同特征,它是对象的模板。对象用于描述现实中的个体,它是类的实例。
封装性
使用private对属性和方法进行封装。封装的成员不能被类外面之间访问,只有对象内部可以访问。将对象的属性和行为封装起来。
继承性
已存在的用来派生新类的类成为基类,又称为父类以及超类;由已存在的类派生出的新类称为派生类,又称子类。
通过继承,可以得到父类的方法和属性,也可以扩充自己,添加新的属性和方法。“可重用行”。
继承性主要描述的是类与类之间的关系。继承增强了代码的复用性,提高了程序开发效率。
多态
子类继承父类,重写(通过重写实现多态)父类的方法,方法名相同,参数类型和参数个数不同,实现不同的效果。同一操作作用于不同的对象,会产生不同的执行结果。
final关键字
不希望某个类被继承,只能被实例化。
当一个类被继承时,所包含的final方法不能被子类重写。
单例模式
一个类只能被实例化一次。