<?php
//===============================================================
//---------------------------------------------------------------
//php面向对象的程序设计
class MyClass{
	private $Name;
	private $Sex;
	
	function __construct($Name="Stephen",$Sex="Man"){
		$this->Name=$Name;
		$this->Sex=$Sex;
	}
	private function __get($proName){
		return $this->$proName;
	}
	private function __set($proName,$proValue){
		$this->$proName=$proValue;
	}
	private function __isset($proName){
		return isset($this->$proName);
	}
	private function __unset($proName){
		unset($this->$proName);
	}
	private function Demo(){
	}
	function __destruct(){
	}
}
$p=new MyClass("John","Boy");
//===============================================================
//===========================类继承的总结=======================
//继承,只能单继承
class Demo(){}
class One extends Demo(){}

//抽象类
abstract class Demo{}
//抽象类不可创建对象必须用子类去继承
class Test extends Demo(){}

//接口
interface Demo{}
interface Demo2{}
//接口继承接口
interface Test extends Demo{}

//实现接口

//类实现接口
class Test implements Demo,Demo2{}
//抽象类实现接口,再用普通类实现
abstract class Test implements Demo,Demo2{}
//继承类(可为抽象类)并实现接口
class Demo extends Test implements Demo,Demo2{}

//多态
interface Demo{}
class One implements Demo{}
class Two implements Demo{}
//调用方法不变,创建不同对象实现不同效果
$p=new One;//$p = new Two;
$p->TestOne();
$p->TestTwo();
//========================魔术方法==============================
//--------------------------------------------------------------
__construct		//构造方法	(啃死tr爱克特)
__destruct		//析构方法

__call()			//调用不存在方法转向该方法
__callStatic()	//调用一个不存在的静态方法转向该方法,此方法必须是静态的

__get()			//外部调用封装后的属性时调用
__set()			//外部设置封装后的属性时调用

__isset()		//外部用isset()检测封装属性时调用
__unset()		//外部用unset()删除封装属性时调用

__sleep()		//使用serialize将对象转换为字符串时自动调用,必须返回一个数组
__wakeup()		//反串行化初始化对象时调用 unserialize反串行化

__toString()	//输出对象时调用,用此查看对象属性,返回值必须是字符串

__clone()		//克隆对象为对象初始化

__autoload();	//自动加载

__invoke()
__set_state()
//----------------------------------------------------------
//--------------------__get()-------------------------------
//此魔术方法用来获取私有的成员属性
function __get($proName){
	return $this->$proName;
}
//取得成员属性的方法
echo $p->Name;
//用此方法可以控制一些值的获取
//----------------------------------------------------------
//--------------------__set()-------------------------------
//此方法用来设置私有的成员属性
function __set($proName,$proValue){
	$this->$proName=$proValue;
}
//设置私有成员属性的方法
$p->Name="Stephen";
//用此方法可以限制一些值的设置
//----------------------------------------------------------
//--------------------__isset()-----------------------------
//判断对象中私有属性是否存在
function __isset($proName){
	return isset($this->$proName);
}
//对象外判断私有属性是否存在的方法
if(isset($p->Name)){
	echo "存在";
}else{
	echo "不存在";
}
/*此方法可以在对象外面判断对象中私有属性是否存在与限
制对一些私有属性的判断*/
//----------------------------------------------------------
//--------------------__unset()-----------------------------
//在对象外删除私有属性
function __unset($proName){
	unset($this->$proName);
}
//在对象外删除私有属性的方法
unset($p->Name);
//此方法可以限制一些私有属性的删除
//---------------------__call()-----------------------------
//----------------------------------------------------------
//在调用对象中不存在的方法时转向该方法
//$methodName不存在的方法名,$args(数组)不存在的参数
function  __call($methodName,$args){
	echo $methodName."此方法不存在";
}
//调用一个不存在的静态方法时调用
//此方法必须是静态的
static function  __callStatic($methodName,$args){
	echo $methodName."此方法不存在";
}
//----------------------------------------------------------
//---------------------__toString()-------------------------
//直接输出对象引用时自动调用
function __toString(){
	return $this->Name .$this->Sex . $this->Height;
}
echo $p;
//----------------------------------------------------------
//---------------------__clone()----------------------------
//使用clone去克隆对象
class MyClass{
	protected $Name;
	
	function __construct($Name="Stephen"){
		$this->Name=$Name;
	}
	//__clone()就是在克隆对象时为克隆的对象初始化,同__construct
	function __clone($Name="New Stephen"){
		$this->Name=$Name;	//此时的$this代表克隆后的对象,$that代表原对象
	}
	function __destruct(){
		echo $this->Name;
	}
}
$p=new MyClass();
$p=clone $pTwo;	//使用P去克隆对象,将出现两个各自独立的对象

//---------------------------------------------------------------
//-----------------------__sleep()-------------------------------
class B{
	public $name = 'Stepohen';
	
	//此方法不写时返回所有属性
	public function __sleep(){
		return array('name');
	}
	public function __wakeup(){
		echo 'wakeup';
	}
}
$b = new B;
//此时调用__sleep方法
$str = serialize($b);
//此时调用__wakeup方法
$Obj = unserialize($str);
//---------------------------------------------------------------
//-------------------__autoload()自动加载类---------------------

//自动加载类
function __autoload($className){//$className为类名
	include "./".$className.".class.php";
}
$p = new MyClass();
//例:
//类名规则
"HelloAction.class.php"
"WorldAction.class.php"
"MondayModel.class.php"
"Smarty.class.php"
function __autoload($className){
	if(substr($className,-6)=="Action"){
		include(APP_CLASS_PATH .'Action/'.$className.".class.php");
	}else if(substr($className,-5)){
		include(APP_CLASS_PATH .'Model/'.$className.".class.php");
	}else if($className=="Smarty"){
		include CMS_ROOT ."Smarty/Smarty.class.php";
	}else{
		include(APP_CLASS_PATH .'Action/'.$className.".class.php");
	}
}
//----------------------------------------------------------
//--------------对象序列化__sleep()__wakeup()--------------
//对象序列化(串行化)可以将对象内容长时间保存
serialize()	//对象序列化
unserialize()	//对象反序列化
class MyClass{
	protected $Name;
	protected $Age;
	protected $Sex;
	
	function __construct($Name){
		$this->Name=$Name;
	}
	//在对象串行化时调用,返回一个数组,只将数组中包含的属性串行化*
	function __sleep(){
			return array("Name","Age");
	}
	//在对象反序列化时将对象初始化,同__construct*
	function __wakeup(){
		$this->Age=$this->Age +1;
	}
	function Say(){
		return $this->Name;
	}
}
//对象序列化过程
$p=new MyClass("Stephen");
$str=serialize($p);	//将对象序列化
file_put_contents("Hello.txt",$str);	//将对象序列化

//对象反序列化化过程
$str=file_get_contents("Hello.txt");	//读出对象文件
$p=unserialize($str);	//将对象反序列化
$p->Say();	//调用对象

//=========================继承性===============================
//--------------------------------------------------------------
/* 
	子类继承父类的方法,子类可以访问父类的属性和方法,
	从子类中父类也可以访问子类的属性和方法
*/
class MyClass{
	protected $Name;
	protected $Sex;
	protected $Age;
	
	function __construct($Name="Stephen",$Sex="Man",$Age="24"){
		$this->Name=$Name;
		$this->Sex=$Sex;
		$this->Age=$Age;
	}
	protected function Say(){
		return "Say";
	}
}

//使用extends关键子继承父类,这样子类包含了父类的所有东西
class NewMyClass extends MyClass{
	//在子类中添加一些新的内容
	protected $Height;
	protected $Weight;
	
	protected function Run(){
	}
}

//子类还可以继续继承子类的方法
class NewMyclassTow extends NewMyclass{
	protected $Hobby;
	
	//继承父类的构造方法并加入新的方法
	function __construct($Name="Stephen",$Sex="Man",$Age="24",$Height="178cm"){
		parent::__construct($Name="Stephen",$Sex="Man",$Age="24");
		$this->Height=$Height;
	}
	//子类重载父类的方法,方法名要相同
	//子类可以扩大权限,但不可以缩小权限(父类为protected 子类不可为private)
	protected function $Say(){
		//重载父类方法的同时将父类方法继承过来
		//父类类名::方法名 或 parent::方法名
		parent::Say();
		return "NewSay";
	}
}
//对NewMyClassTow实例化对象
//虽然子类中没有构造方法但是继承了父类的构造方法
$p=new NewMyClassTow("Hello","Gril","22");
$p->Say();
$p->Run();

//========================常用关键字============================
//---------------------------------------------------------------
//final关键字只能修式类和成员方法
//用final修饰的类不能被继承,被修饰的方法不能被覆盖,最终版本
final class MyClass{
	final function Demo(){
	}
}
//----------------------static-------------------------------*
//静态成员只能访问静态成员
//static 关键字只能修饰成员属性与成员方法
//静态成员存储在初始化静态段中
class MyClass{
	static $Name="Stephen";
	static $Sex;
	
	static function Demo(){
		//内部访问静态成员的方法
		return self::$Name;
	}
}
//对象外部访问静态成员,类名::属性或方法
echo MyClass::$Name;
echo MyClass::Demo();
//对静态成员改值
MyClass::$Name="Hello";
//-------------------单态设计模式---------------------------
class DB{
	//1.声明一个私有的静态成员属性,用于存放本类实例化的对象
	private static $Obj=null;
	
	//2.使用private封装后只能在类的内部创建对象
	private function __construct(){
	}
	//3.声明一个公有的静态成员,使之外部不创建对象而直接访问到本方法
	static function getInstance(){
		if(is_null(self::$Obj)) //如果本类中的$Obj为空,说明还没有被实例化过
			self::$Obj=new self();//实例化本类对象(The key)*
		return self::$Obj;	//返回本类的对象
	}
	//其他方法
	function Hello(){
		echo "Hello";
	}
}
//只能用静态方法取得DB类的对象*
$db=DB::getInstance();
//访问对象中的成员
$db->Hello();
//---------------------const---------------------------------
//const在类中声明常量
class MyClass{
	const HOST="localhost";
	
	function Host(){
		//在类内部访问常量
		return self::HOST;
	}
}
//在类外部访问常量
echo MyClass::HOST;
//============================抽象类=============================
//---------------------------------------------------------------
/*抽象类的作用就是定义一些规范让子类按照规范完成功能*/
//抽象类中必须有一个抽象方法,同时抽象类必须用abstract修饰
abstract class Demo{
	protected $Name;
	
	//这是抽象方法,必须用abstract修饰
	abstract function Demo();
	//抽象类中可以声明其他类
	function Test(){
	}
}
//抽象类不可创建对象,所以必须要用子类去继承
class Test extends Demo(){
	//将父类的方法重载
	function Demo(){
		return "Hello";
	}
}

//==========================接口技术=============================
//---------------------------------------------------------------
//接口中只能有抽象方法,不用abstract修饰,
//接口中不可有变量只有常量
//接口必须是public
interface Demo{		//interface接口声明修饰词
	const HOST="localhost";
	const USER="Admin";
	public function Test();
	function TestUser();
}
//可以访问接口的静态变量
echo Demo::HOST;

//接口继承接口
interface Test extends Demo{
	//对上一个接口内容扩展
	function TestTwo();
	function TestThree();
}

//1.用抽象类实现接口用,关键子implements
abstract class Test implements Demo{
}
//2.用类实现接口,前提是必须实现所有的抽象方法
class Test implements Demo{
	function Test(){
	}
	function TestUser(){
	}
}
//----------------------类实现多个接口-------------------------
interface TestOne{
	function One();
}
interface TestTow{
	function Two();
}
//实现多个接口
class Demo implements TsetOne,TestTwo{
	function One(){
	}
	function Two(){
	}
}
//--------------------继承类并实现接口-------------------------*
interface TestOne{
	function One();
}
interface TestTow{
	function Two();
}
//类
class Test{
	function Three(){
	}
}
//继承类并实现接口
class Demo extends Test implements TsetOne,TestTwo{
	function One(){
	}
	function Two(){
	}
}

//=============================多态==============================
//---------------------------------------------------------------
interface Demo{	//接口
	function TestOne();
	function TestTwo();
}
class One implements Demo{
	function TestOne(){
		echo "方式一";
	}
	function TestTwo(){
		echo "方式一";
	}
}
class Two implements Demo{
	function TestOne(){
		echo "方式二";
	}
	function TestTwo(){
		echo "方式二";
	}
}
/*当调用的方法不变,创建不同的对象就可以实现不同的效果,
这就是多态,接口的作用就是保证每个类都有相同的方法*/
$p=new One;

$p->TestOne();
$p->TestTwo();

//=========================函数=================================
//--------------------------------------------------------------
class_exists			//检查类是否已定义
get_class_methods	//返回由类的方法名组成的数组
get_class_vars		//返回由类的默认属性组成的数组 
get_class			//返回对象的类名
get_declared_classes//返回由已定义类的名字所组成的数组
get_declared_interfaces	//Returns an array of all declared interfaces 
get_object_vars		//返回由对象属性组成的关联数组
get_parent_class	//返回对象或类的父类名
interface_exists		//Checks if the interface has been defined
is_a				//如果对象属于该类或该类是此对象的父类则返回 TRUE 
is_subclass_of		//如果此对象是该类的子类,则返回 TRUE 
method_exists		//检查类的方法是否存在
property_exists		//Checks if the object or class has a property
//===============================================================
//---------------------------------------------------------------