<? class Person { // 下面是人的成员属性 var $name; // 人的名子 var $sex; // 人的性别 var $age; // 人的年龄 // 定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值 function __construct($name = "", $sex = "", $age = "") { $this->name = $name; $this->sex = $sex; $this->age = $age; } // 这个人可以说话的方法,说出自己的属性 function say() { echo "我的名子叫:" . $this->name . " 性别:" . $this->sex . " 我的年龄是:" . $this->age . "<br>"; } } $p1 = new Person("张三", "男", 20); // 使用“clone”克隆新对象p2,和p1对象具有相同的属性和方法。 $p2=clone $p1; $p2->say(); ?>
“__clone()”方法可以没有参数,它自 动包含$this和$that两个指针,$this指向复本,而$that指向原本;
<? class Person { // 下面是人的成员属性 var $name; // 人的名子 var $sex; // 人的性别 var $age; // 人的年龄 // 定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值 function __construct($name = "", $sex = "", $age = "") { $this->name = $name; $this->sex = $sex; $this->age = $age; } // 这个人可以说话的方法, 说出自己的属性 function say() { echo "我的名子叫:" . $this->name . " 性别:" . $this->sex . " 我的年龄是:" . $this->age . "<br>"; } // 对象克隆时自动调用的方法, 如果想在克隆后改变原对象的内容,需要在__clone()中重写原本的属性和方法 function __clone() { // $this指的复本p2, 而$that是指向原本p1,这样就在本方法里,改变了复本的属性。 $this->name = "我是假的 $that->name"; $this->age = 30; } } $p1 = new Person("张三", "男", 20); $p2 = clone $p1; $p1->say(); $p2->say(); ?>
上例输出:
我的名子叫:张三 性别:男 我的年龄是:20
我的名子叫:我是假的张三 性别:男 我的年龄是:30
如果一个项目,我们要对一个一模一样的类进行引用,我们可以用__clone()然后,然后对其进行赋值就可以了 省去繁琐的操作
注意被克隆的物体一定是个被实例化过的对象
当我们调用了一个不存在的方法时程序就会报错
此时我们引入了一个错误的处理方法__call();
<?php //这是一个测试的类,里面没有属性和方法 class Test { // 调用不存的方法时自动调用的方法,第一个参数为方法名,第二个参数是数组参数 function __call($function_name, $args) { print "你所调用的函数:$function_name(参数:"; print_r($args); echo ")不存在!<br>"; } } // 产生一个Test类的对象 $test=new Test(); // 调用对象里不存在的方法 $test->demo("one", "two", "three"); // 程序不会退出可以执行到这里 echo "this is a test<br>"; ?>
上例输出结果为:
你所调用的函数: demo(参数:Array ( [0] => one [1] => two [2] => three ) )不存在!
this is a test
在OOP语言中,一个类可以有一个或多个子类,而每个类都有至少一个公有方法做为外部代码访问其的接口。而抽象方法就是为了方便继承而引入的,我们先来看一下抽象类和抽象方法的定义再说明它的用途。
用法:所谓的没有方法体指的是,在方法声明的时候没有大括号以及其中的内容,而是直接在声明时在方法名后加上分号结束,另外在声明抽象方法时还要加一个关键字“abstract”来修饰;
例如:
abstract function fun1(); abstract function fun2();
要点:1.抽象类不能产生实例对象
2.子类必须把父类中的抽象方法全部都实现,否则子类中还存在抽象方法,那么子类还是抽象类,还是不能实例化类
<? abstract class Demo { var $test; abstract function fun1(); abstract function fun2(); function fun3() { ... } } $demo = new Demo(); // 抽象类不能产生实例对象,所以这样做是错的,实例化对象交给子类 class Test extends Demo { function fun1() { ... } function fun2() { ... } } $test = new Test(); // 子类可以实例化对象,因为实现了父类中所有抽象方法 ?>
为了解决多继承的问题,我们引入了接口这个概念
接口:接口是一种特殊的抽象类,抽象类又是一种特殊的类,所以接口也是一种特殊的类
类的定义: class 类名{ … } ,
接口的声明:interface 接口名{ …}
<?php // 定义一个接口使用interface关键字,“One”为接口名称 interface One { // 定义一个常量 const constant = 'constant value'; // 定义了一个抽象方法”fun1” public function fun1(); // 定义了抽象方法”fun2” public function fun2(); } ?>
PHP中不仅一个类可以实现多个接口,也可以在继承一个类的同时实现多个接口, 一定要先继承类再去实现接口;
<?php // 使用extends继承一个类,使用implements实现多个接口 class Four extends 类名一 implemtns 接口一, 接口二, ... { // 所有接口中的方法都要实现才可以实例化对象 ... } ?>
PHP的多态就是多态就是把子类对象赋值给父类引用,然后调用父类的方法,去执行子类覆盖父类的那个方法
<?php // 定义了一个形状的接口,里面有两个抽象方法让子类去实现 interface Shape { function area(); function perimeter(); } // 定义了一个矩形子类实现了形状接口中的周长和面积 class Rect implements Shape { private $width; private $height; function __construct($width, $height) { $this->width = $width; $this->height = $height; } function area() { return "矩形的面积是:" . ($this->width * $this->height); } function perimeter() { return "矩形的周长是:" . (2 * ($this->width + $this->height)); } } // 定义了一个圆形子类实现了形状接口中的周长和面积 class Circular implements Shape { private $radius; function __construct($radius) { $this->radius=$radius; } function area() { return "圆形的面积是:" . (3.14 * $this->radius * $this->radius); } function perimeter() { return "圆形的周长是:" . (2 * 3.14 * $this->radius); } } // 把子类矩形对象赋给形状的一个引用 $shape = new Rect(5, 10); echo $shape->area() . "<br>"; echo $shape->perimeter() . "<br>"; // 把子类圆形对象赋给形状的一个引用 $shape = new Circular(10); echo $shape->area() . "<br>"; echo $shape->perimeter() . "<br>"; ?>
为了方便传输,我们可以进行将对象转化为二进制的输出 我们将这个过程称为序列化
第一种情况就是把一个对象在网络中传输的时候要将对象串行化
第二种情况就是把对象写入文件或是数据库的时候用到串行化。
序列化:serialize()
反序列化:unserialize()
<? class Person { // 下面是人的成员属性 var $name; // 人的名子 var $sex; // 人的性别 var $age; // 人的年龄 // 定义一个构造方法参数为属性姓名$name、性别$sex和年龄$age进行赋值 function __construct($name = "", $sex = "", $age = "") { $this->name = $name; $this->sex = $sex; $this->age = $age; } // 这个人可以说话的方法, 说出自己的属性 function say() { echo "我的名子叫:" . $this->name . " 性别:" . $this->sex . " 我的年龄是:" . $this->age . "<br>"; } } $p1 = new Person("张三", "男", 20); $p1_string = serialize($p1); // 把一个对象串行化,返一个字符串 echo $p1_string . "<br>"; // 串行化的字符串我们通常不去解析 $p2 = unserialize($p1_string); // 把一个串行化的字符串反串行化形成对象$p2 $p2->say(); ?>
上例输出值为:
O:6:"Person":2:{s:4:"name";s:4:"张三";s:3:"age";i:20;}
我的名子叫:张三 性别: 我的年龄是:40
我们在mVC的架构中经常看到这么一个函数__autoload()函数
<?php function __autoload($classname) { require_once $classname . '.php'; } //MyClass1类不存在时,自动调用__autoload()函数,传入参数”MyClass1” $obj = new MyClass1(); //MyClass2类不存在时,自动调用__autoload()函数,传入参数”MyClass2” $obj2 = new MyClass2(); ?>