php面向对象编程(三)

<?
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();
?>

  

上一篇:Give root password for maintenance(or type control -D to continue)


下一篇:大数据学习day22------spark05------1. 学科最受欢迎老师解法补充 2. 自定义排序 3. spark任务执行过程 4. SparkTask的分类 5. Task的序列化 6. Task的多线程问题