PHP--学习笔记---03面向对象程序设计

1.一个最简单的类设计及使用
<?php
class Cat{
	public $name;
	public $age;
	public $color;

	public function eat(){
		echo "eat some food";
	}
}
$jiafei=new Cat();
$jiafei->name="jiafeimao";
echo $jiafei->name;
echo "<br/>";
$jiafei->eat();
?>

结果:
jiafeimao
eat some food


类定义语句也可以写成如下形式,使用var关键字,声明一个成员属性,成员方法可以省略掉访问控制符

class Cat{
	var $name;
	var $age;
	var $color;

	function eat(){
		echo "eat some food";
	}
}

public function Cat(){
		echo "here is my construct method";
	}

以上方法创建构造函数已经被弃用了

2.使用$this 关键字

和java的this类似

<?php
class Cat{
	
	var $name;
	var $age;
	var $color;

	function eat($who){
		$this->name=$who;
		echo $this->name." eat some food";
	}
}
$jiafei=new Cat();
echo $jiafei->name;
$jiafei->eat("蓝猫");
?>

蓝猫 eat some food

2.使用__construct 关键字创建构造方法
<?php
class Cat{
	
	var $name;
	var $age;
	var $color;

	//构造方法使用两个下划线表示
	function __construct($name,$age,$color){
		$this->name=$name;
		$this->age=$age;
		$this->color=$color;
	}

	function eat($breakFirst){
		echo $this->color."的".$this->age."岁的".$this->name."爱吃".$breakFirst;
	}
}
$jiafei=new Cat("小白",1,"白色");
$jiafei->eat("小老鼠");
echo "<br/>**<br/>";

class Dog{
	var $name;
	var $age;
	var $color;

	//构造方法使用两个下划线表示,同时可以设置默认值
	function __construct($name="旺财",$age=1,$color="黑色"){
		$this->name=$name;
		$this->age=$age;
		$this->color=$color;
	}

	function say(){
		echo "我的名字叫:".$this->name." 我是".$this->color." 今年".$this->age."岁了";
		echo "<br/>";
	}
}

$dog1=new Dog("哈士奇",2,"花斑");
$dog2=new Dog("哈士奇",4);
$dog3=new Dog("哈士奇");

$dog1->say();
$dog2->say();
$dog3->say();
?>

结果:
白色的1岁的小白爱吃小老鼠
**
我的名字叫:哈士奇 我是花斑 今年2岁了
我的名字叫:哈士奇 我是黑色 今年4岁了
我的名字叫:哈士奇 我是黑色 今年1岁了

3.使用__destruct 关键字的析构方法

析构是用来在对象销毁时,销毁内存的,不太常用,不知道php有没有自动内存清理

function __destruct(){
}
4.封装之私有成员—private及get,set方法

使用private进行修饰,其作用和功能和java的private非常详实
对于使用private修饰的成员属性及成员方法,可以使用get,set函数进行获取。

<?php
class Person{
	var $name;
	var $age;
	var $gender;

	function __construct($name="张三",$gender="男",$age=1){
		$this->name=$name;
		$this->gender=$gender;
		$this->age=$age;

	}

	public function setName($name){
				$this->name=$name;
	}
	public function setGender($gender){
				$this->gender=$gender;
	}
	public function setAge($age){
				$this->age=$age;
	}

	public function getName(){
		return $this->name;
	}
	public function getGender(){
		return $this->gender;
	}
	public function getAge(){
		return $this->age;
	}
}

$person1=new Person();
$person1->setName("王五");
$person1->setGender("女");
$person1->setAge(23);
echo "<br/>".$person1->name."  ".$person1->gender."  ".$person1->age."<br/>";
$person2=new Person();
echo "<br/>".$person2->getName()."  ".$person2->getGender()."  ".$person2->getAge()."<br/>";

?>

结果:

王五 女 23

张三 男 1

5.魔术方法—__set(),__get()及__isset,__unset方法

__set():同java
__get():同java
__isset():检查私有属性是否存在
__unset():删除对象中私有属性

  • __set()
    作用是:
    在程序运行过程中为私有的成员属性设置值,不需要有任何返回值。但需要两个参数,第一个参数需要传入在为私有属性设置值时的属性名( $propertyname),第二个参数需要传入为属性设置的值( $propertyvalue)。
    一般不建议对该方法使用private符。浏览器提示警告
<?php
class Person{
	var $name;
	var $age;
	var $gender;

	function __construct($name="张三",$gender="男",$age=1){
		$this->name=$name;
		$this->gender=$gender;
		$this->age=$age;

	}
	/*
	声明魔术方法需要连个参数,直接为私有属性时自动调用(在构造的时候就调用),并可以屏蔽一些非法赋值
	@param String $propertyName
	@param mixed  $propertyValue
	 */

	function __set($propertyName,$propertyValue){
		//开始对非法数据拦截,这里只拦截gender属性和age属性,实际上只是屏蔽想要屏蔽的属性
		if ($propertyName=="gender") {
			if (!($propertyValue=="男" || $propertyValue=="nv")) {
				//如果非法则直接返回空
				return ;
			}
		}

		if ($propertyName=="age") {
			if (!($propertyValue<0 || $propertyValue>100)) {
				//如果非法则直接返回空
				return ;
			}
		}

		//正式传值
		$this->$propertyName=$propertyValue;

	}
	//公开的方法
	public function say(){
		echo "我的名字:".$this->name." 我的性别:".$this->gender." 我的年龄:".$this->age;
	}
}

$person1=new Person("李四","女",34);
$person1->say();

?>

结果:
我的名字:李四 我的性别:女 我的年龄:34

  • __gett()

当获取私有属性的值得时候,自动调用该方法,返回私有属性的值。自动设置的参数为属性名即$propertyName

  • **__isset(),__unset()**检测和删除私有属性
    isset是检测共有属性的,如果设定了__isset(),当传入的是私有属性时,则自动调用__isset()来检测私有属性。
    unset()是删除共有属性,如果设定了__unset(),当传入的是私有属性时,则调用__unset()方法
<?php
class Person{
	private  $name;
	private $age;
	private $gender;

	function __construct($name="张三",$gender="男",$age=1){
		$this->name=$name;
		$this->gender=$gender;
		$this->age=$age;

	}
	/*
	声明魔术方法需要连个参数,直接为私有属性时自动调用(在构造的时候就调用),并可以屏蔽一些非法赋值
	@param String $propertyName
	@param mixed  $propertyValue
	 */

	function __set($propertyName,$propertyValue){
		//开始对非法数据拦截,这里只拦截gender属性和age属性,实际上只是屏蔽想要屏蔽的属性
		if ($propertyName=="gender") {
			if (!($propertyValue=="男" || $propertyValue=="nv")) {
				//如果非法则直接返回空
				return ;
			}
		}

		if ($propertyName=="age") {
			if (!($propertyValue<0 || $propertyValue>100)) {
				//如果非法则直接返回空
				return ;
			}
		}

		//正式传值
		$this->$propertyName=$propertyValue;

	}

	function __get($propertyName){
		if ($propertyName=="age") {
			if ($this->age>60) {
				return $this->age+5;
			}else if ($this-age>25 && $this-age<=60) {
				return $this->age+10;
			}else{
				return $this->$propertyName;
			}
		}else{
			return $this->$propertyName;
		}
		
	}

	function __isset($propertyName){
		if ($propertyName=="name") {//如果传入name属性,则返回false,实则不允许检测name属性
			return false;
		}else{
			return isset($this->$propertyName);
		}
	}
	function __unset($propertyName){
		if ($propertyName=="name") {//如果传入name属性,实则不允许删除name属性
			return ;
		}else{
			return isset($this->$propertyName);
		}
	}

	//公开的方法
	public function say(){
		echo "我的名字:".$this->name." 我的性别:".$this->gender." 我的年龄:".$this->age;
	}
}

$person1=new Person("李四","女",34);
$person1->say();
echo "<br/>";
$person2=new Person("朱八","男",64);
echo $person2->name."  ".$person2->gender."  ".$person2->age;
echo "<br/>";
var_dump(isset($person1->name));
echo "<br/>";
var_dump(isset($person1->gender));
echo "<br/>";
var_dump(isset($person1->name));
echo "<br/>";
var_dump(isset($person1->age));
?>

结果:
我的名字:李四 我的性别:女 我的年龄:34
朱八 男 69
bool(false)
bool(true)
bool(false)
bool(true)

6.继承
<?php
class Person{
	var $name;
	var $gender;
	var $age;

	function __construct($name,$gender,$age){
		$this->name=$name;
		$this->gender=$gender;
		$this->age=$age;
	}
	function say(){
		echo "我名叫 ".$this->name." 我是 ".$this->gender."我几年" .$this->age."岁了";
	}
}

class Student extends Person{
	var $school;
	function study($school){
		echo $this->name."在".$school." 努力地学习 ";
	}
}

$person1=new Person("张三","女",34);
$person1->say();
echo "<br/>";

$student1=new Student("李四","男",24);
$student1->say();
echo "<br/>";
$student1->study("清华大学");
echo "<br/>";

$person2=new Student("王五","男",24);
$person2->say();
echo "<br/>";
$person2->study("清华大学");
?>

结果:
我名叫 张三 我是 女我几年34岁了
我名叫 李四 我是 男我几年24岁了
李四在清华大学 努力地学习
我名叫 王五 我是 男我几年24岁了
王五在清华大学 努力地学习

6.封装—private私有成员的访问

private修饰符修饰,并且自定义public权限的getXXX,和setXXX函数访问私有成员变量

7.封装—四个魔术方法(见前章)
8.封装—访问控制类型

在这里插入图片描述

9.封装—子类重载父类的方法

即子类继承父类方法后,对继承来的父类方法重写(覆盖)

<?php
class Person{
	var $name;
	var $gender;
	var $age;

	function __construct($name,$gender,$age){
		$this->name=$name;
		$this->gender=$gender;
		$this->age=$age;
	}
	function say(){
		echo "我名叫 ".$this->name." 我是 ".$this->gender."我几年" .$this->age."岁了";
	}
}

class Student extends Person{
	var $school;
	function __construct($name,$gender,$age,$school){
		$this->name=$name;
		$this->gender=$gender;
		$this->age=$age;
		$this->school=$school;
	}
	function study($school){
		echo $this->name."在".$school." 努力地学习 ";
	}

	function say(){
		echo "我名叫 ".$this->name." 我是 ".$this->gender."我几年" .$this->age."岁了,我在".$this->school."读书";
	}
}


$student1=new Student("李四","男",24,"北京大学");
$student1->say();


?>

结果:
我名叫 李四 我是 男我几年24岁了,我在北京大学读书

10.封装—子类直接调用父类方法,使用parent::方法名
<?php
class Person{
	var $name;
	var $gender;
	var $age;

	function __construct($name,$gender,$age){
		$this->name=$name;
		$this->gender=$gender;
		$this->age=$age;
	}
	function say(){
		echo "我名叫 ".$this->name." 我是 ".$this->gender."我几年" .$this->age."岁了";
	}
}

class Student extends Person{
	var $school;
	function __construct($name,$gender,$age,$school){
		parent::__construct($name,$gender,$age);
		$this->school=$school;
	}
	function study($school){
		echo $this->name."在".$school." 努力地学习 ";
	}

	function say(){
		parent::say();
		echo ",我在".$this->school."读书";
	}
}


$student1=new Student("李四","男",24,"北京大学");
$student1->say();
?>

结果:
我名叫 李四 我是 男我几年24岁了,我在北京大学读书

11.封装—final关键字

可以使用在类或者类方法前,但是不能标识成员属性。
final标识的类,不能被继承
final标识的成员方法,在子类中不能被覆盖

12.封装—static关键字

同java的static
static修饰的成员方法或者成员属性属于类而不属于实例
类的静态属性类似于函数的全局变量,通过类名来直接访问
格式如下:
类名::静态成员方法
类名::静态成员属性


使用self来访问其他静态成员
格式为:
self::静态成员方法
self::静态成员属性

<?php
class Person{
	static $native;
	var $name;
	var $gender;
	var $age;
	static function showNative(){
		echo "我是 ".self::$native."人";
	}

}

Person::$native="中国";
Person::showNative();

?>

结果是:
我是 中国人

13.封装–单态(单例)设计模式

即类只有一个实例,如连接数据库操作,只需要连接一次数据库就可以了,不需要反复连接数据库(反复创建数据库实例)

<?php
class DB{
	private static $obj=null;//声明一个私有的静态成员属性$obj
	//构造方法,使用private封装后,则只能在类的内部使用new去创建对象
	private function __construct(){
		//z在这个方法中去完成一系列数据库连接操作
		echo "连接数据库成功";

	}

	//只有通过这个方法才能返回本类的对象,该方法是静态方法,用类名调用
	static function getInstance(){
		if (is_null(self::$obj)) {//如果本类中的$obj为空,说明还没有被实例化过
			self::$obj=new self;//实例化本类对象
		}
		return self::$obj;
	}

	//执行sql语句完成对数据库的操作
	function query($sql){
		echo $sql;
	}
}

//只能使用静态方法getInstance()去获取DB类的对象
$db=DB::getInstance();
$db->query("select * from user");
?>

结果:
连接数据库成功select * from user
ps:
1、要编写单态(单例)设计模式,就必须让一个类,只能实例化一个对象。要向让一个类只能实例化一个对象,就要先让一个类不能实例化对象。这里通过使用static修饰后,就无法通过实例的方式获得本例的静态对象 $obj。但由于使用了private封装,还是能在类的内部进行实例化。
2、本例通过geInstance来实例化本类对象。(self:: $obj=new self())实例化本类对象

14.封装–const(常量)关键字

一般情况定义常量使用define()来定义,但要将类中的成员属性定义为常量,则只能使用const关键字。
使用const标识的类的成员属性,成为常量,其访问使用self关键字访问。也不能用对象来访问,
标识为常量的属性是只读的,不能重新赋值。
因此在声明常量时一定要给定初值(因为以后没有机会再赋值)
使用const声明的常量名称前不需要使用$美元符,且常量名通常为大写

<?php
class Person{
	const HOME="地球";
	var $name;

	function __construct($name){
		$this->name=$name;
	}
	function live(){
		echo $this->name."居住在".self::HOME;
	}
}

$person1=new Person("小明");
$person1->live();
?>

结果:
小明居住在地球

15.封装–instanceof关键字

instanceof关键字可以判断对象是类的实例,类的子类,还是实现了类的接口,并进行相应操作

<?php
class Person{
	const HOME="地球";
	var $name;

	function __construct($name){
		$this->name=$name;
	}
	function live(){
		echo $this->name."居住在".self::HOME;
	}
}

class Student extends Person{

}
$person1=new Person("小明");
$student1=new Student("小马");
var_dump( $person1 instanceof Person);
echo "<br>";
var_dump( $student1 instanceof Person);

?>

结果:
bool(true)
bool(true)

16.封装–克隆__clone()

独立副本,两个地址空间,互补干扰
如果需要克隆的时候,重新对克隆后的副本成员属性赋初值,可以添加魔术方法__clone();该方法无需参数,自动包含 $this,和 $that两个对象的引用。
$this:是副本对象的引用
$that:是原本对象的引用

<?php
class Person{
	const HOME="地球";
	var $name;

	function __construct($name){
		$this->name=$name;
	}
	function live(){
		echo $this->name."居住在".self::HOME;
	}

	function __clone(){
		$this->name=$this->name."副本";
	}
}


$person1=new Person("小明");
$person2=clone $person1;

echo $person1::HOME;
echo "<br>";
echo $person2::HOME;
echo "<br>";
echo $person1->live();
echo "<br>";
echo $person2->live();

?>

结果:
地球
地球
小明居住在地球
小明副本居住在地球

17.封装–类中的通用方法__toString()方法

当类中定义了__tostring()方法时,如果执行echo 对象时将自动调用该方法,如果没有定义__toString方法则报错

<?php
class Person{
	private $food;
	function __construct($food){
		$this->food=$food;
	}
	function __toString(){
		return $this->food;
	}
}


$person1=new Person("三明治");
echo $person1;
?>

结果:
三明治

18.封装–__call()

如果调用对象中不存在的方法,会自动调用该魔术方法
需包含两个参数,一个是调用的函数名: $functionName,一个是调用是输入的参数列表 $args

<?php
class Person{
	private $food;
	function __construct($food){
		$this->food=$food;
	}
	function __toString(){
		return $this->food;
	}

	function __call($functionName,$args){//这两个参数很重要
		echo "您调用的".$functionName."方法不存在<br/>";
		echo "您输入了一下参数<br>";
		foreach ($args as $value) {
			echo $value."<br/>";
		}
	}
}


$person1=new Person("三明治");
echo $person1->fachai("发财具备的素质","发财具备的机会");

结果:
您调用的fachai方法不存在
您输入了一下参数
发财具备的素质
发财具备的机会

19.封装–自动加载类__autolaod()

当引用某个方法的时候,如果找不到类,就去目录中查找,然后用include包含进来
貌似该方法已经过时,被spl_autoload_register()取代

<?php
/*
声明一个自定加载类的模式方法,$className是需要加载的类名称字符串
 */
function __autoload($className){
	//在方法中使用include包含类所在的文件
	include(strtolower($className).".class.php");
}

$obj=new User();
$obj2=new Student();
?>
20.封装–对象串行化(序列化)Serialization()

serialize()函数
与java的对象序列化类似,将对象序列化成二进制串后在网络中传输。
对象需要持久保持时,将对象序列化后写入文件或者数据库中(java中的持久化的意思)
unserialize()反序列化函数
返回对象

实际上就是把对象存放到磁盘或者数据库里,有点文件流操作和dao操作的意思。

<?php
class Person{
	var $name;
	var $age;

	function __construct($name,$age){
		$this->name=$name;
		$this->age=$age;
	}

	function eat($food){
		echo $this->age."岁的".$this->name."吃".$food;
	}

}
$p1=new Person("张大民",34);
$p1->eat("香蕉");

$fileSerialize=serialize($p1);
file_put_contents("file.txt", $fileSerialize);

结果:
34岁的张大民吃香蕉
在这里插入图片描述
文件内部:
O:6:“Person”:2:{s:4:“name”;s:9:“张大民”;s:3:“age”;i:34;}

反序列化

<?php
class Person{
	var $name;
	var $age;

	function __construct($name,$age){
		$this->name=$name;
		$this->age=$age;
	}

	function eat($food){
		echo $this->age."岁的".$this->name."吃".$food;
	}

}
$p1=new Person("张大民",34);
$p1->eat("香蕉");
echo "<br/>||||||<br/>";
$fileSerialize=serialize($p1);
file_put_contents("file.txt", $fileSerialize);


$fileunserialize=file_get_contents("file.txt");
$p2=unserialize($fileunserialize);
$p2->eat("苹果");
?>

结果:
34岁的张大民吃香蕉
|||||||
34岁的张大民吃苹果

__sleep()方法和__wakeup()方法

<?php
class Person{
	var $name;
	var $age;
	var $address;

	function __construct($name,$age,$address){
		$this->name=$name;
		$this->age=$age;
		$this->address=$address;
	}

	function eat($food){
		echo $this->age."岁的".$this->name."吃".$food;
	}
	//序列化时自动调用
	function __sleep(){
		//数组中的成员被序列化
		$arr=array("name","age","address");
		return $arr;

	}

	//反序列化时自动调用,没有参数也没有返回值
	function __wakeup(){
		$this->name="天山老妖";
		$this->age=1000;
	}

}
$p1=new Person("张大民",34,"天津");
$p1->eat("香蕉");
echo "<br/>|||||||<br/>";
$fileSerialize=serialize($p1);
file_put_contents("file.txt", $fileSerialize);


$fileunserialize=file_get_contents("file.txt");
$p2=unserialize($fileunserialize);
$p2->eat("苹果");
?>

结果是:
在这里插入图片描述
34岁的张大民吃香蕉
|||||||
1000岁的天山老妖吃苹果

21.封装–抽象类

同java的抽象类,使用abstract来修饰,抽象方法没有方法体。抽象类可以有成员属性和构造方法
抽象方法不能被实例化
抽象方法可以被继承,并需要在子类中去实现
抽象类中可以声明正常的方法体(这点和java不同)

<?php
abstract class Person{
	//可以拥有成员属性
	var $name;
	var $country;
	//可以拥有构造函数
	function __construct($name,$country){
		$this->name=$name;
		$this->country=$country;
	}
	//一个抽象方法,php的抽象方法也可以不用abstract修饰
	abstract function speak($language);
	//一个抽象方法
	abstract function eat();

	//也可以拥有正常的方法
	function work(){
		echo "work hard as a dog";
	}
}

//使用继承来实现抽象类的抽象方法这点和java不同
class Student extends Person{
	function speak($language){
		echo $this->country."人".$this->name."说".$language;
	}

	function eat(){
		echo "我们吃好吃的";
	}
}

$student1=new Student("张三","中国");
$student1->speak("国语");
echo "<br/>";
$student1->eat();
echo "<br/>";
$student1->work();
?>

结果:
中国人张三说国语
我们吃好吃的
work hard as a dog

22.封装–接口技术interface

php和java一样只能接受单继承,但可以实现多接口
接口中的方法都必须是抽象方法,
接口中不能声明成员变量,只能使用const关键字声明为常量的成员属性。
所有接口的成员都必须有public的访问权限
使用interface关键字表示
格式如下:

interface 接口名{
常量成员
抽象方法
}

接口可以使用extends去继承另外一个接口
子类通过implements实现接口

<?php
interface Person{
	const HOME="流浪地球";
	function drive();
	function fly();
}

interface Student extends Person{
	function study();
	function read();
}

class college implements Student{
	function drive(){
		echo "i want dirve at ".self::HOME;
	}
	function fly(){
		echo "i am flying, i am flying in the sky";
	}

	function study(){
		echo "good good study,day day up";
	}

	function read(){
		echo "read book and break ten thousands paper";
	}

}

$freshman=new college();
$freshman->drive();
echo "<br/>";
$freshman->fly();
echo "<br/>";
$freshman->study();
echo "<br/>";
$freshman->read();

结果:
i want dirve at 流浪地球
i am flying, i am flying in the sky
good good study,day day up
read book and break ten thousands paper

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值