您的位置:首页 > 编程语言 > PHP开发

PHP学习-面向对象

2015-12-11 16:38 621 查看
本文大概介绍php中面向对象涉及的一些基础知识。主要以例子为主,文字方面的描述可能会欠缺点。有些知识点会在不同的例子中穿插。

如果不正确的地方,忘包涵。

继承

任何语言的面向对象处理,都离不开继承这个话题,所谓继承就是一个子类继承父类的所有特性,同时子类可以还可以添加自己的一些特性。

注意在php中,继承只能继承自一个父类,不能同时继承多个父类。

1.单层继承,子类的上面只有一个父类

<?php

/**
* 父类Base1
*/
class Base1 {

/**
* 父类1的属性
* 属性名为$AttrBase1
* @var string
*/
public $AttrBase1;

/**
* 构造函数,实例化对象时调用
* @param string $AttrBase1 属性名
*/
function __construct($AttrBase1) {
$this->AttrBase1 = $AttrBase1;
}

/**
* 父类1的方法
* 输出属性$Base1name的值
*/
public function OutPut() {
echo 'Base1 父类属性=' . $this->AttrBase1 . '<br>';
}

}

/**
* 子类Child1,继承自父类Base1
* 子类Child1中没有定义任何属性与方法,但是它包含了Base1的所有元素,包括构造函数
*/
class Child1 extends Base1 {

}

//实例化一个Child1对象,调用了父类的构造方法把值赋给了$AttrBase1
$objChild1 = new Child1("父类属性");
$objChild1->OutPut(); //输出【Base1 父类属性=父类属性】

/**
* 子类Child2,继承自父类Base2
* 子类Child2中增加了如下特性:
* 自己的属性$AttrChild1
* 自己的方法ChildOutPut
* 自己的构造函数,同时还调用父类的构造函数
*/
class Child2 extends Base1 {

/**
* 子类自有的属性
* 属性名为$AttrChild1
* @var string
*/
public $AttrChild1;

/**
* 子类的构造函数
* @param string $AttrBase1 父类属性名
* @param string $AttrChild1 子类属性名
*/
function __construct($AttrBase1, $AttrChild1) {
//为自身的属性赋值
$this->AttrChild1 = $AttrChild1;
//调用父类的构造函数为父类中的属性赋值
parent::__construct($AttrBase1);
}

/**
* 子类自身的方法
*/
public function ChildOutPut() {
echo 'Child2 父类属性=' . $this->AttrBase1 . ' 子类属性=' . $this->AttrChild1 . '<br>';
}

}

//实例化一个Child2对象,并初始化了父类与子类的属性,调用子类自己的方法进行了输出
$objChild2 = new Child2("父类属性", "子类属性");
$objChild2->ChildOutPut(); //输出【Child2 父类属性=父类属性 子类属性=子类属性】
?>

2.多层继承,子类的上面有多个父类(父类也是继承是其他类)

在实际使用中,比较常见的就是这种继承,对象需要多次进行归纳,这样才能让代码维护的比较好。

下面这个例子是,Child1继承自Base2,Base2继承自Base1。Child1中可以引用Base1与Base2中定义的属性。

/**
* 父类Base1
*/
class Base1 {

/**
*
* @var string $AttrBase1 Base1属性
*/
public $AttrBase1;

}

/**
* 父类Base2
*/
class Base2 extends Base1 {

/**
*
* @var string $AttrBase2 Base2属性
*/
Public $AttrBase2;

}

/**
* 子类Child1
*/
class Child1 extends Base2 {

/**
*
* @var string $AttrChild1 Child属性
*/
public $AttrChild1;

/**
* 子类构造方法,可以同时访问2个父类中的属性
* @param string $AttrBase1 Base1属性
* @param string $AttrBase2 Base2属性
* @param string $AttrChild1 Child1属性
*/
function __construct($AttrBase1, $AttrBase2, $AttrChild1) {
$this->AttrBase1 = $AttrBase1;
$this->AttrBase2 = $AttrBase2;
$this->AttrChild1 = $AttrChild1;
}

/**
* 输出父类及子类中的属性
*/
public function OutPut() {
echo 'Base1属性=' . $this->AttrBase1 . ' Base2属性=' . $this->AttrBase2 . ' Child1属性=' . $this->AttrChild1 . '<br>';
}

}

//这里有个注意点,当用双引号传入如下参数时会报错
//因为在双引号中有$符号的会当做变量解析,但是$AttrBase1并没有定义
$objChild1 = new Child1('$AttrBase1', '$AttrBase2', '$AttrChild1');
$objChild1->OutPut();

类中属性与方法的访问控制

在定义类里面的属性或者方法时,可以在它们前面加上一些前缀,对属性或方法的方法进行控制。主要有3种控制方法,如下所列:

1.public

公有类成员,可以在任何地方进行访问(定义该成员的类【自身】,该类的子类,其他类)。

/**
* Base类
*/
class Base {

/**
*
* @var string $AttrBase 公有属性
*/
public $AttrBase;

/**
* 构造函数
*/
function __construct() {
$this->AttrBase = 'AttrBase';
}

/**
* 公有方法
*/
public function BaseFunction() {

echo '属性=' . $this->AttrBase . '<br>';
}

}

//实例化Base类
$objBase = new Base();
//在类的外部访问类的public方法
$objBase->BaseFunction();
//在类的外部访问类的public属性
echo '访问Base的public属性=' . $objBase->AttrBase . '<br>';

/**
* Child类
*/
class Child extends Base {

/**
* 子类构造函数
*/
function __construct() {
//在子类里面访问父类的public属性
$this->AttrBase = 'AttrChild';
}

}

$objChild = new Child();
//在子类的外部访问父类的public方法
$objChild->BaseFunction();
//在子类的外部访问父类的public属性
echo '访问Base的public属性=' . $objChild->AttrBase . '<br>';


2.protected

受保护的成员,可以在定义该成员的类的内部访问或者在子类的内部访问,不能在类的外部进行访问。

/**
* Base类
*/
class Base {

/**
*
* @var string $AttrBase 受保护属性
*/
protected $AttrBase;

/**
* 构造函数
*/
function __construct() {
$this->AttrBase = 'AttrBase';
}

/**
* 公有方法
*/
public function BaseFunction() {
//在自身类里面访问protected属性
echo '属性=' . $this->AttrBase . '<br>';
}

}

//实例化Base类
$objBase = new Base();
//在类的外部访问类的public方法
$objBase->BaseFunction();
//不能在类的外部访问类的protected属性(会报错)
//echo '访问Base的protected属性=' . $objBase->AttrBase . '<br>';

/**
* Child类
*/
class Child extends Base {

/**
* 子类构造函数
*/
function __construct() {
//在子类的内部访问父类protected属性
$this->AttrBase = "ChildClass";
}

public function ChildFunction() {
//在子类的内部访问父类protected属性
echo '子类属性=' . $this->AttrBase . '<br>';
}

}

$objChild = new Child();
//通过子类的public函数访问父类的protected属性
$objChild->ChildFunction();


3.private

私有的类成员,只能在定义成员的类的内部进行访问,不能在子类中访问,也不能在外部进行访问。

/**
* Base类
*/
class Base {

/**
*
* @var string $AttrBase 私有属性
*/
private $AttrBase;

/**
* 构造函数
*/
function __construct() {
$this->AttrBase = 'AttrBase';
}

/**
* 公有方法
*/
public function BaseFunction() {
//在自身类里面访问private属性
echo '属性=' . $this->AttrBase . '<br>';
}

}

//实例化Base类
$objBase = new Base();
//通过类的public方法类的private属性
$objBase->BaseFunction();

//不能在类的外部访问类的private属性(会报错)
//echo '访问Base的private属性=' . $objBase->AttrBase . '<br>';

class Child extends Base {

/**
* 子类的构造函数
*/
function __construct() {
//子类里面不能访问父类的private属性(不能给父类的AttrBase属性赋值)
//在这里会在子类里面创建一个AttrBase属性
$this->AttrBase = 'child';
}

/**
* 子类方法
*/
public function ChildFunction() {
echo $this->AttrBase . '<br>';
}

}

$objChild1 = new Child();
//调用父类方法输出为空,因为在构造函数中不能给父类属性赋值
$objChild1->BaseFunction();
//调用子类方法有输出,因为在子类中创建了AttrBase变量
$objChild1->ChildFunction();
//子类中有了AttrBase这个属性
echo $objChild1->AttrBase . '<br>';


Static(静态)关键字

static关键字大概有如下属性

1.静态属性用于保存类的公有数据,在类的不同实例化对象中访问的值都是相同的

2.静态成员不需要实例化就可以进行访问,通过类的名称在类定义外访问静态成员

3.静态方法里面只能访问静态属性

4.类的内部可以使用self::或static::进行访问,在子类里面可以通过parent::来访问父类的静态属性或方法

/**
* Base类
*/
class Base {

/**
*
* @var static string $AttrStatic 静态属性
*/
public static $AttrStatic = 'StaticAttr';

/**
*
* @var string $AttrGen 常规属性
*/
private $AttrGen = 'AttrGen';

/**
* 输出静态属性
*/
public function EchoStatic() {
echo '静态属性self访问=' . self::$AttrStatic . '<br>';
echo '静态属性static访问=' . static::$AttrStatic . '<br>';
}

/**
* 静态方法输出静态属性
*/
public static function EchoGen() {
//静态方法里面只能访问静态属性
echo '静态方法里面方法静态属性=' . self::$AttrStatic . '<br>';
//静态方法里面不能访问非静态属性,会报错
//echo '静态方法里面方法静态属性=' . $this->AttrGen . '<br>';
}

}

//实例化对象$objBase1,输出StaticAttr
$objBase1 = new Base();
$objBase1->EchoStatic();
//实例化对象$objBase2,也输出输出StaticAttr
$objBase2 = new Base();
$objBase2->EchoStatic();
//在外部通过类名加::访问类里面的静态方法或属性
Base::EchoGen();
echo '类的外部通过Base::AttrStatic访问类的静态属性=' . Base::$AttrStatic . '<br>';
//修改类的静态属性
Base::$AttrStatic = 'StaticAttr change';
echo '类的外部修改类的静态属性<br>';
Base::EchoGen();

/**
* Child子类
*/
class Child extends Base {

/**
* 输出父类中的静态属性
*/
public function EchoParentStaticAttr() {
echo 'Child子类中访问父类的静态方法=' . parent::$AttrStatic . '<br>';
}

}

$objChild = new Child();
$objChild->EchoParentStaticAttr();


重写(overwrite)与重载(overload)

1.重写

子类重写了父类的同名方法,子类需要根据需求对父类中的方法进行一些自己的处理。

/**
* Base类
*/
class Base {

/**
* 父类OutPut方法
*/
public function OutPut() {
echo 'Base类的OutPut方法' . '<br>';
}

}

/**
* Child子类
*/
class Child extends Base {

/**
* 子类OutPut方法,覆盖父类的OutPut方法
*/
public function OutPut() {
echo 'Base类的OutPut方法在子类中被覆盖' . '<br>';
}

}

$objChild = new Child();
$objChild->OutPut();


2.重载(overload)

相同的方法名的方法,但是根据传进来的不同参数类型或不同参数个数,执行不同的方法。c#可以实现,在php中不允许有同名的方法,这边借用__call来实现一个重载。

/**
* Base类
*/
class Base {

/**
* 当实例化的对象访问不存在的函数时调用
* @param type $name 函数名
* @param type $arguments 参数个数
*/
function __call($name, $arguments) {
switch ($name) {
case "OutPut":
if (count($arguments) == 1) {
//如果只有一个参数
echo '一个参数' . '<br>';
} else if (count($arguments) == 2) {
//如果只有二个参数
echo '二个参数' . '<br>';
} else {

}
break;

default:
break;
}
}

}

$objBase = new Base();
//输出一个参数
$objBase->OutPut(1);
//输出二个参数
$objBase->OutPut(1, 2);

Final关键字

从final的字面意思来看,就是最终的意思,它所表达的就是某个类不能被继承或某个函数不能被重写。

1.final类

/**
* Base类,有final修饰不能被继承
*/
final class Base {

/**
*
* @var int $AttrBase Base属性
*/
public $AttrBase = 1;

}

/**
* 这里会报错,因为Base类为final的,不能被继承
*/
class Child extends Base {

}


2.final方法

/**
* Base类
*/
class Base {

/**
* final方法,在子类中不能被重写
*/
final public function FinalFunction() {
echo 'base final function';
}

/**
* 非final方法,在子类中可以被重写
*/
public function OtherFunction() {
echo 'base other function';
}

}

/**
* Child继承自Base
*/
class Child extends Base {

/**
* 报错,不能重写父类的final方法
*/
public function FinalFunction() {
echo 'child final function';
}

/**
* 不报错,可以重写父类的方法
*/
public function OtherFunction() {
echo 'child other function';
}

}

接口

interface关键字用于定义接口,接口里面不需要有方法的具体实现,而是在使用的它的类中实现。可以使用implements关键字来实现某个接口,接口中的所有方法

在类中都需要具体实现。

/**
* Say接口
*/
interface Say {

/**
* 说中文
* @param string $word 说的话
*/
public function SayChinese($word);

/**
* 说英文
* @param string $word 说的话
*/
public function SayEnglish($word);
//会报错,接口中不能定义protected方法
//protected function ProtectedSay($word) ;
//会报错,接口中不能定义private方法
//private function PrivateSay($word) ;
}

/**
* Human继承自接口Say,需要具体实现接口里面的SayChinese与SayEnglish方法
* 这里注意,在实现接口里面的方法的时候,方法的前缀只能是public
*/
class Human implements Say {

/**
* 具体实现SayChinese方法
* @param string $word
*/
public function SayChinese($word) {
echo 'say chinese ' . $word . '<br>';
}

/**
* 具体实现SayEnglish方法
* @param string $word
*/
public function SayEnglish($word) {
echo 'say english ' . $word . '<br>';
}

}

/**
* Woman继承自Human
*/
class Woman extends Human {

/**
* woman说话
*/
public function WomanSay() {
echo $this->SayChinese('你好');
echo $this->SayEnglish('hello');
}

}

$objWoman = new Woman();
$objWoman->WomanSay();

不能用接口来实例化对象,如下操作会报错。

/**
* Say接口
*/
interface Say {

/**
* 说中文
* @param string $word 说的话
*/
public function SayChinese($word);

/**
* 说英文
* @param string $word 说的话
*/
public function SayEnglish($word);
}

//这里会报错,不能通过接口实例化对象
$objSay = new Say();
可以使用instanceof关键字来判断某个对象是否实现了某个接口。

/**
* Say接口
*/
interface Say {

/**
* 说中文
* @param string $word 说的话
*/
public function SayChinese($word);

/**
* 说英文
* @param string $word 说的话
*/
public function SayEnglish($word);
}

/**
* WomanSay继承接口Say
*/
class WomanSay implements Say {

public function SayChinese($word) {
echo 'chinese';
}

public function SayEnglish($word) {
echo 'english';
}

}

$objWomanSay = new WomanSay();
//这里输出true,$objWomanSay实现了Say接口
var_dump($objWomanSay instanceof Say);
接口可以通过extends来继承别的接口。

/**
* Say接口
*/
interface Say {

/**
* 说中文
* @param string $word 说的话
*/
public function SayChinese($word);

/**
* 说英文
* @param string $word 说的话
*/
public function SayEnglish($word);
}

/**
* HumanSay接口继承自Say
*/
interface HumanSay extends Say {

/**
* 打招呼
*/
public function SayHello($word);
}

/**
* WomanSay继承接口Say
*/
class WomanSay implements HumanSay {

//SayChinese具体实现
public function SayChinese($word) {
echo 'chinese' . '<br>';
}

//SayEnglish
public function SayEnglish($word) {
echo 'english' . '<br>';
}

//SayHello
public function SayHello($word) {
echo 'hello' . '<br>';
}

}

$objWomanSay = new WomanSay();
$objWomanSay->SayChinese('');
$objWomanSay->SayEnglish('');
$objWomanSay->SayHello('');


多态

对接口的不同实现类中,同一个方法的具体实现不一样,就叫做多态。
/**
* 接口Say
*/
interface Say {

//接口方法,SayWord
public function SayWord();
}

/**
* China继承自接口Say
*/
class China implements Say {

/**
* China-SayWord具体实现
*/
public function SayWord() {
echo 'say chinese' . '<br>';
}

}

/**
* English继承自接口Say
*/
class English implements Say {

/**
* English-SayWord具体实现
*/
public function SayWord() {
echo 'say english' . '<br>';
}

}

//China与English,对SayWord的方法具体实现不同
$objChina = new China();
$objEnglish = new English();
$objChina->SayWord();
$objEnglish->SayWord();


抽象类

abstract用于定义抽象类,抽象类中可以有抽象方法(在方法前增加abstract前缀,不需要具体实现)或者普通方法。可以使用extends关键字来继承抽象类,在子类中需要具体实现抽象类中的抽象方法。

/**
* 抽象类Human
*/
abstract class Human {

/**
* 抽象方法Say,可以用public修饰
*/
abstract public function Say();

//会报错,抽象方法不能用private修饰
//abstract private function PrivateSay();

/**
* 抽象方法ProtectedSay,可以用protected修饰
*/
abstract protected function ProtectedSay();

/**
* 普通方法
*/
public function GenalFunction() {
echo 'GenalFunction' . '<br>';
}

}

/**
* Woman继承自抽象类
* 这里需要注意的:
* 1.如果抽象方法为public修饰,在具体实现时也必须是public
* 2.如果抽象方法为protected修饰,在具体实现时可以为public或protected
*/
class Woman extends Human {

/**
* 抽象方法Say的具体实现
*/
public function Say() {
echo 'Say' . '<br>';
}

/**
* 抽象方法ProtectedSay的具体实现
*/
protected function ProtectedSay() {
echo 'ProtectedSay' . '<br>';
}

}

$objWoman = new Woman();
$objWoman->Say();
//会报错,protected方法在类的外部不能访问
//$objWoman->ProtectedSay();
$objWoman->GenalFunction();
抽象类同样可以用extends来继承别的抽象类。

/**
* 抽象类Human
*/
abstract class Human {

/**
* 抽象方法Say,可以用public修饰
*/
abstract public function Say();

//会报错,抽象方法不能用private修饰
//abstract private function PrivateSay();

/**
* 抽象方法ProtectedSay,可以用protected修饰
*/
abstract protected function ProtectedSay();

/**
* 普通方法
*/
public function GenalFunction() {
echo 'GenalFunction' . '<br>';
}

}

/**
* 抽象类可以继承别的抽象类
*/
abstract class Woman extends Human {

/**
* 生小孩的方法
*/
abstract public function HaveBaby();
}

/**
* Woman继承自抽象类
* 这里需要注意的:
* 1.如果抽象方法为public修饰,在具体实现时也必须是public
* 2.如果抽象方法为protected修饰,在具体实现时可以为public或protected
*/
class WomanClass extends Woman {

/**
* 抽象方法Say的具体实现
*/
public function Say() {
echo 'Say' . '<br>';
}

/**
* 抽象方法ProtectedSay的具体实现
*/
public function ProtectedSay() {
echo 'ProtectedSay' . '<br>';
}

/**
* 抽象方法HaveBaby的具体实现
*/
public function HaveBaby() {
echo 'HaveBaby' . '<br>';
}

}

$objWoman = new WomanClass();
$objWoman->Say();
$objWoman->ProtectedSay();
$objWoman->GenalFunction();
$objWoman->HaveBaby();

面向对象中一些有趣的方法

1.__construct与__destruct

构造方法__construct在为一个类实例化对象时会调用,可以在构造方法里面为类的某些属性赋值或做某些初始化操作。

/**
* Base类
*/
class Base {

/**
*
* @var string $AttrBase 属性
*/
private $AttrBase;

/**
* 初始化方法,在使用对象之前进行相关的初始化处理
*/
private function Init() {
echo '初始化实例,通过参数$AttrBase=' . $this->AttrBase . '<br>';
}

/**
* 构造方法,在实例化对象时调用
* @param type $AttrBase
*/
function __construct($AttrBase) {
//为类的属性赋值
$this->AttrBase = $AttrBase;
$this->Init();
}

}
//实例化对象时传入参数,会调用__construct为类的私有属性赋值
$objBase=new Base('hello world');
析构方法__destruct在程序的结束时会被调用,可以在此方法里面来释放使用到的一些资源。

/**
* Base类
*/
class Base {

/**
*
* @var string $AttrBase 属性
*/
private $AttrBase;

/**
* 初始化方法,在使用对象之前进行相关的初始化处理
*/
private function Init() {
echo '初始化实例,通过参数$AttrBase=' . $this->AttrBase . '<br>';
}

/**
* 构造方法,在实例化对象时调用
* @param type $AttrBase
*/
function __construct($AttrBase) {
//为类的属性赋值
$this->AttrBase = $AttrBase;
$this->Init();
}

/**
* 析构方法,程序结束时调用
*/
function __destruct() {
$this->AttrBase = null;
echo '释放属性资源$AttrBase.$AttrBase=' . $this->AttrBase . '<br>';
}

}

//实例化对象时传入参数,会调用__construct为类的私有属性赋值
$objBase = new Base('hello world');
//可以看到$AttrBase的值被置为空了
//在程序结束时输出了文字【释放属性资源$AttrBase.$AttrBase=】

如果不想在程序结束时才调用析构方法,而是在之前调用该怎么处理呢。可以为对象赋值null来实现。

/**
* Base类
*/
class Base {

/**
*
* @var string $AttrBase 属性
*/
private $AttrBase;

/**
* 初始化方法,在使用对象之前进行相关的初始化处理
*/
private function Init() {
echo '初始化实例,通过参数$AttrBase=' . $this->AttrBase . '<br>';
}

/**
* 构造方法,在实例化对象时调用
* @param type $AttrBase
*/
function __construct($AttrBase) {
//为类的属性赋值
$this->AttrBase = $AttrBase;
$this->Init();
}

/**
* 析构方法,程序结束时调用
*/
function __destruct() {
$this->AttrBase = null;
echo '释放属性资源$AttrBase.$AttrBase=' . $this->AttrBase . '<br>';
}

}

//实例化对象时传入参数,会调用__construct为类的私有属性赋值
$objBase = new Base('hello world');
//通过把对象设置为null来提前调用析构方法
$objBase=null;
//可以看到在下面输出文字之前就已经调用了类Base的析构方法了
echo '我才是程序的结束。';
这里还有个有趣的现象,如果使用$obj2=$obj1来把$obj1的值赋给$obj2的话,在将$obj1=null时并不会调用析构方法。因为$obj1与$obj2为不同引用,在$obj1=null后$obj2还对类Base有使用,所以会调用析构方法。除非把$obj2=null或者到程序结束才会调用析构方法。

注意使用$obj2=$obj1时,如果修改任一对象里面的值,都会影响另外一个对象,如果不想有值篡改的复制,应该使用clone方法,后面会说。

/**
* Base类
*/
class Base {

/**
*
* @var string $AttrBase 属性
*/
private $AttrBase;

/**
* 初始化方法,在使用对象之前进行相关的初始化处理
*/
private function Init() {
echo '初始化实例,通过参数$AttrBase=' . $this->AttrBase . '<br>';
}

/**
* 构造方法,在实例化对象时调用
* @param type $AttrBase
*/
function __construct($AttrBase) {
//为类的属性赋值
$this->AttrBase = $AttrBase;
$this->Init();
}

/**
* 析构方法,程序结束时调用
*/
function __destruct() {
$this->AttrBase = null;
echo '释放属性资源$AttrBase.$AttrBase=' . $this->AttrBase . '<br>';
}

}

//实例化对象时传入参数,会调用__construct为类的私有属性赋值
$objBase = new Base('hello world');
//将$objBase赋值给$objBase1
$objBase1=$objBase;
//在将$objBase=null时并不会调用析构方法(在程序结束才会调用)
$objBase=null;
//但是如果也将$objBase1=null那么就会在程序结束之前调用析构方法了
//$objBase1=null;
//可以看到在下面输出文字之前就已经调用了类Base的析构方法了
echo '我才是程序的结束。<br>';
当使用$obj2=&$obj1赋值时,它们指向的相同引用,在将任一对象赋值为null时都会调用析构方法。

/**
* Base类
*/
class Base {

/**
*
* @var string $AttrBase 属性
*/
private $AttrBase;

/**
* 初始化方法,在使用对象之前进行相关的初始化处理
*/
private function Init() {
echo '初始化实例,通过参数$AttrBase=' . $this->AttrBase . '<br>';
}

/**
* 构造方法,在实例化对象时调用
* @param type $AttrBase
*/
function __construct($AttrBase) {
//为类的属性赋值
$this->AttrBase = $AttrBase;
$this->Init();
}

/**
* 析构方法,程序结束时调用
*/
function __destruct() {
$this->AttrBase = null;
echo '释放属性资源$AttrBase.$AttrBase=' . $this->AttrBase . '<br>';
}

}

//实例化对象时传入参数,会调用__construct为类的私有属性赋值
$objBase = new Base('hello world');
//通过如下方式,将$objBase赋值给$objBase1
$objBase1=&$objBase;
//在将$objBase=null或$objBase1=null时都会调用析构方法
//$objBase=null;
$objBase1=null;
//可以看到在下面输出文字之前就已经调用了类Base的析构方法了
echo '我才是程序的结束。<br>';


2.__tostring

当一个对象被当作字符串使用时,会调用这个方法,比如echo $obj。

/**
* Base类
*/
class Base {

/**
* 在对象被当作字符串使用时调用
* @return string
*/
function __toString() {
echo 'haha<br>';
//最后必须有return处理
return '调用了__toString方法<br>';
}

}

$objBase = new Base();
//如果Base中没有__toString的话,此处就会报错
echo $objBase;

3.__invoke

当对象被方法来调用时调用,比如$obj(1)。

/**
* Base类
*/
class Base {

/**
* 对象被当作方法来使用时调用
*/
function __invoke() {
//将传入的参数合并为字符串
echo '传入方法的参数=' . implode(',', func_get_args());
}

}

$objBase = new Base();
//如果Base中没有__invoke的话,此处就会报错
$objBase(4, 5, 6);

4.__call与__callStatic

当调用对象不存在的方法时,__call会调用。

/**
* Base类
*/
class Base {

/**
* 当调用的方法在对象中不存在时
* @param string $name 方法名
* @param array $arguments 参数
*/
function __call($name, $arguments) {
echo '调用了不存在的方法' . $name . ',使用了参数=' . implode(' ', $arguments) . '<br>';
}

}

$objBase=new Base();
//输出【调用了不存在的方法Say,使用了参数=I see I come I conquer】
$objBase->Say('I see','I come','I conquer');
同理当调用对象不存在的静态方法时,__callStatic会调用。

/**
* Base类
*/
class Base {

/**
* 当调用的静态方法在对象中不存在时
* 因为需要在外部调用所以需要用public修饰
* @param string $name 方法名
* @param array $arguments 参数
*/
public static function __callStatic($name, $arguments) {
echo '调用了不存在的静态方法' . $name . ',使用了参数=' . implode(' ', $arguments) . '<br>';
}

}

//输出【调用了不存在的静态方法Say,使用了参数=I see I come I conquer】
Base::Say('I see', 'I come', 'I conquer');

以上的2个方法可以用于方法的重载(overloading),同一方法的名称调用可以对应不同的方法实现。

5.__set与__get

当给不存在的属性赋值时会调用__set()方法。实际应用中可以在类中定义一个数组来存放相关属性。

/**
* Base类
*/
class Base {

/**
* 用于保存不存在的属性
* @var array  $arrayAttr
*/
private $arrayAttr = array();

/**
* 设置类中不存在的属性时调用
* @param type $name 属性名
* @param type $value 属性值
*/
function __set($name, $value) {
$this->arrayAttr[$name] = $value;
}

/**
* 输出属性数组现有值
*/
public function OutPutAttr() {
echo '属性数组现有值:';
foreach ($this->arrayAttr as $value) {
echo $value . ' ';
}
echo '<br>';
}

}

$objBase = new Base();
$objBase->attr1 = "i see";
//输出【属性数组现有值:i see 】
$objBase->OutPutAttr();
$objBase->attr2 = "i come";
//输出【属性数组现有值:i see i come 】
$objBase->OutPutAttr();
$objBase->attr3 = "i conquer";
//输出【属性数组现有值:i see i come i conquer 】
$objBase->OutPutAttr();

当获取对象不存在的属性的时候会调用__get()。

/**
* Base类
*/
class Base {

/**
* 用于保存不存在的属性
* @var array  $arrayAttr
*/
private $arrayAttr = array();

/**
* 设置类中不存在的属性时调用
* @param type $name 属性名
* @param type $value 属性值
*/
function __set($name, $value) {
$this->arrayAttr[$name] = $value;
}

/**
* 当获取对象不存在的属性时会调用
* @param type $name 属性名
* @return string 返回值
*/
function __get($name) {
//如果属性已经设置过,则返回对应的属性值,否则返回提示信息
if(array_key_exists($name, $this->arrayAttr)){
return $this->arrayAttr[$name];
}
else{
return '属性不存在';
}
}

/**
* 输出属性数组现有值
*/
public function OutPutAttr() {
echo '属性数组现有值:';
foreach ($this->arrayAttr as $value) {
echo $value . ' ';
}
echo '<br>';
}

}

$objBase = new Base();
//////设置属性
echo '设置属性<br>';
$objBase->attr1 = "i see";
//输出【属性数组现有值:i see 】
$objBase->OutPutAttr();
$objBase->attr2 = "i come";
//输出【属性数组现有值:i see i come 】
$objBase->OutPutAttr();
$objBase->attr3 = "i conquer";
//输出【属性数组现有值:i see i come i conquer 】
$objBase->OutPutAttr();

//////获取属性
echo '获取属性<br>';
echo $objBase->attr1.'<br>';
echo $objBase->attr4.'<br>';


6.__isset()与__unset()

当对不可访问的属性调用isset()时会调用__isset()。

/**
* Base类
*/
class Base {

/**
* 用于保存不存在的属性
* @var array  $arrayAttr
*/
private $arrayAttr = array();

/**
* 设置类中不存在的属性时调用
* @param type $name 属性名
* @param type $value 属性值
*/
function __set($name, $value) {
$this->arrayAttr[$name] = $value;
}

/**
* 当获取对象不存在的属性时会调用
* @param type $name 属性名
* @return string 返回值
*/
function __get($name) {
//如果属性已经设置过,则返回对应的属性值,否则返回提示信息
if (array_key_exists($name, $this->arrayAttr)) {
return $this->arrayAttr[$name];
} else {
return '属性不存在';
}
}

/**
* 检查某个属性是否已设置
* @param type $name 属性名称
*/
function __isset($name) {
if (array_key_exists($name, $this->arrayAttr)) {
return true;
} else {
return false;
}
}

/**
* 输出属性数组现有值
*/
public function OutPutAttr() {
echo '属性数组现有值:';
foreach ($this->arrayAttr as $value) {
echo $value . ' ';
}
echo '<br>';
}

}

$objBase = new Base();
//////设置属性
echo '设置属性<br>';
$objBase->attr1 = "i see";
//输出【属性数组现有值:i see 】
$objBase->OutPutAttr();
$objBase->attr2 = "i come";
//输出【属性数组现有值:i see i come 】
$objBase->OutPutAttr();
$objBase->attr3 = "i conquer";
//输出【属性数组现有值:i see i come i conquer 】
$objBase->OutPutAttr();

//检查属性
//属性attr1已有,返回true
echo var_dump(isset($objBase->attr1));
//属性attr4没有,返回false
echo var_dump(isset($objBase->attr4));
当对不可访问的属性调用unset()时会调用__unset()。

/**
* Base类
*/
class Base {

/**
* 用于保存不存在的属性
* @var array  $arrayAttr
*/
private $arrayAttr = array();

/**
* 设置类中不存在的属性时调用
* @param type $name 属性名
* @param type $value 属性值
*/
function __set($name, $value) {
$this->arrayAttr[$name] = $value;
}

/**
* 当获取对象不存在的属性时会调用
* @param type $name 属性名
* @return string 返回值
*/
function __get($name) {
//如果属性已经设置过,则返回对应的属性值,否则返回提示信息
if (array_key_exists($name, $this->arrayAttr)) {
return $this->arrayAttr[$name];
} else {
return '属性不存在';
}
}

/**
* 检查某个属性是否已设置
* @param type $name 属性名称
*/
function __isset($name) {
if (array_key_exists($name, $this->arrayAttr)) {
return true;
} else {
return false;
}
}

/**
* 删除某个属性
* @param type $name 属性名
*/
function __unset($name) {
if (array_key_exists($name, $this->arrayAttr)) {
unset($this->arrayAttr[$name]);
}
}

/**
* 输出属性数组现有值
*/
public function OutPutAttr() {
echo '属性数组现有值:';
foreach ($this->arrayAttr as $value) {
echo $value . ' ';
}
echo '<br>';
}

}

$objBase = new Base();
//////设置属性
echo '设置属性<br>';
$objBase->attr1 = "i see";
//输出【属性数组现有值:i see 】
$objBase->OutPutAttr();
$objBase->attr2 = "i come";
//输出【属性数组现有值:i see i come 】
$objBase->OutPutAttr();
$objBase->attr3 = "i conquer";
//输出【属性数组现有值:i see i come i conquer 】
$objBase->OutPutAttr();

//检查属性
//属性attr1已有,返回true
echo var_dump(isset($objBase->attr1));
//删除attr1
unset($objBase->attr1);
//属性attr1被删除了,返回false
echo var_dump(isset($objBase->attr1));


7.__chone

当某个对象被clone时调用。

直接clone一个对象的话,新对象里面的值与原来的一样,但是可能想在clone的时候对某些属性进行改变,就可以在__chone实现。

/**
* Base类
*/
class Base {

/**
* 属性
* @var type $AttrBase
*/
public $AttrBase;

/**
* 构造方法
* @param type $AttrBase
*/
function __construct($AttrBase) {
$this->AttrBase = $AttrBase;
}

/**
* 当chone对象是调用
*/
function __clone() {
$this->AttrBase = 'hello moon';
}

}

$objBase = new Base('hello world');
//实例化对象
echo $objBase->AttrBase . '<br>';
//clone对象
$objBase1 = clone $objBase;
//如果没有__chone则输出的值同$objBase值
//如果有__chone则输出的值为在此方法里为属性新赋的值
echo $objBase1->AttrBase . '<br>';
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: