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