
PHP
PHP
PPHHPP类实例教程(一):开始
从OOP(面向对象)的视角看,不应区分语言。无论是C++、无论是Java、无论是.net还有
更多面向对象的语言,只要你了解了OOP的真谛,便可以跨越语言,让你的思想轻松的跳
跃。便没有对于Java、.net 、 PHP 之间谁强谁弱的争执了。
希望这个介绍PHP5面向对象编程(OOP)的资料能让初学者受益,能让更多的PHPer开始
转向OOP的编程过程。
相对PHP4,PHP5在面向对象方面改变了很多。我们将只介绍PHP5环境下的面向对象。而
我们必须改变自己来跟随PHP5的发展。如果代码结果 在你的环境下执行不一致,请确认
你的环境为PHP5。
我们假设读者没有任何面向对象的知识,即使你是第一次听说OOP,也可以读懂这文章。
但我希望你必须对PHP有一些了解。
在后面我们将使用一些例子,来逐渐分析PHP5的OOP基础。
面向对象只解决了两个问题,代码的可扩展性、 代码的可维护性。
下一节我们将学习类和对象基础部分
PHP
PHP
PPHHPP类实例教程(二):类和对象的基础部分
EverythingisObject
EverythingisObject
EEvveerryytthhiinnggiissOObbjjeecctt:万事万物皆对象
面向对象的编程(OOP)思想力图使对计算机语言中对事物的描述与现实世界中该事物的本
来面目尽可能的一致。(面向对象语言与我们的生活是相通的,面向对象语言学习起来其实
很简单。在应用中更符合我们的生活逻辑。)
Class/Object:类(class)和对象(object)是面向对象方法的核心概念。
类是对一类事物描述,是抽象的、概念上的定义;
(类好像是在图纸上设计的楼房,楼房设计出来了,但这个楼房并不存在。)
对象是实际存在的该类事物的每个个体,因而也称实例(instance)。
(对象是实实在在存在的,照着楼房的设计图纸,高楼盖起来,可以住进去了。在计算机中,
可以理解为,在内存中创建了实实在在存在的一个内存区域存储 着这个对象。)
创建对象的过程称为创建对象也称为实例化。
看下面的图示,一张楼房的图纸创建了多个别墅(对象)。
思考一下:
它们外观一样么?
它们结构一样么?
它们是一个对象么?
PHP5
PHP5
PPHHPP55中的类和对象
我们先建立一个基础的类。
PHP中使用关键字 class 来定义一个类。类的命名一般使用首字符大写,而后每个单词首字
符大写连接的方式方便阅读。
classPerson{
}
?>
这样,我们就拥有了第一个PHP类。
----------------------- 页面 2-----------------------
我们继续来使用这个类,使用 ne
w 这个关键字创建对象
$p=newPerson();
也可以写成
$p=newPerson;
但不建议使用后面的这种方式。
PHP PHP5
PHP PHP5
PPHHPP类实例教程(三):PPHHPP55类中的属性
属性:用来描述对象的数据元素称为对象的属性(也称为数据/状态),在PHP5中,属性指
在class中声明的变量。在声明变量时,必须使用 publicprivateprotected 之一进行修饰,定
义变量的访问权限。(publicprivateprotected三者的区别将在以后讲解)
属性的使用:通过引用变量的-> 符号调用变量指向对象的属性。
在方法内部通过 $this-> 符号调用同一对象的属性。
classPerson
{
public$name="NoName";//定义 public属性$name
public$age=20;//定义public属性$age
}
$p=newPerson();// 创建对象
echo"".$p->name;//输出对象$p的属性$name
echo"
";
echo"".$p->age;//输出$age属性
?>
我们还可以改变属性的值,当然要注意的改变属性的值是通过public来修饰的
我们修改一下这个例子:
classPerson
{
public$name="NoName";//公共 变量$name
public$age=20;//公共变量$age
}
$p=newPerson();
$p->name="Tom";//我是Tom
$p->age=25;//年龄25
echo"".$p->name;//输出名字
echo"
";
echo"".$p->age;//年龄
?>
创建一个Person的对象,改变这个对象的属性。为它命名,查看它的名字。你就是机器里
面这个Person对象的上帝,按照你定义的规则,这个实实在在内存中的Person对象被创建
了,而且它有了可以改变的属性。
属性的初值
----------------------- 页面 3-----------------------
在PHP5中,在属性定义可以不设置初值,或者赋予以下红色类型的初值。
PHP中简单类型有8种,分别是:
四种标量类型:
布尔型(boolean)
整型(integer)
浮点型(float)(浮点数,也作“double”)
字符串(string)
两种复合类型:
数组(array)
对象(object)
最后是两种特殊类型:
资源(resource)
NULL
PHP PHP5
PHP PHP5
PPHHPP类实例教程(四):PPHHPP55类中的方法
方法:对对象的属性进行的操作称为对象的方法(也称为行为/操作)。
过程 函数 方法
过程:过程是编制程序时定义的一个语句序列,用来完成某种指定的操作。
函数:函数有返回值,也是定义的语句序列。
方法:在面向对象概念中,类里面的一段语句序列。
一般来说,在面向对象概念中,函数和方法两个名词是通用的。
通过方法读取属性
下面的例子将属性设置为private ,同时声
明了public的getName()方法,用来获取属性$name
的值,调用getName()方法就会通过return$this->name 返回 $name 的值。
classPerson
{
private$name="NoName";//private 成员$name
publicfunctiongetName(){
return$this->name;
}
}
$newperson=newPerson();
echo"".$newperson->getName();
?>
注意:这里,方法内部调用本地属性时,使用 $this->name来获取属性。在这个例子中,设
置了公开的getName()方法,即用户只能获取$name, 而无法改变他的值。这就是封装的好处。
封装指的是将对象的状态信息(属性)和行为(方法)捆绑为一个逻辑单元的机制。
PHP5中通过将数据封装、声明为私有的(private),再提供一个或多个公开的(public)方法
实现对该属性的操作,以实现下述目的:
防止对封装数据的未经授权的访问。使用者只能通过事先定制好的方法来访问数据,可以便
地加入控制逻辑,对属性的不合理操作;
----------------------- 页面 4-----------------------
有利于保证数据的完整性;
便于修改,增强代码的可维护性;
方法的参数
通过方法定义时的参数,可以向方法内部传递变量。
如下第5行,定义方法时定义了方法参数$_a。使用这个方法时,可以向方法内传递参数变量。
方法内接受到的变量是局部变量,仅在方法内部有效。可以通过向属性传递变量值的方式,
让这个变量应用于整个对象。
classPerson
{
private$a;
functionsetA($_a){
$thia->a=$_a;
}
functiongetA(){
return$this->a;
}
}
$newperson=newPerson();
$newperson->setA(100);
echo$newperson->getA();
?>
如果声明这个方法有参数,而调用这个方法时没有传递参数,或者参数数量不足,系统会报
出错误。如果参数数量超过方法定义参数的数量,PHP就忽略多于的参数,不会报错。可
以在函数定义时为参数设定默认值。 在调用方法时,如果没有传递参数,将使用默认值填
充这个参数变量。
classA
{
public$name="tom";
}
classPerson
{
private$a;
functionsetA($_a){
$this->a=$_a;
}
functiongetA(){
return$this->a;
}
}
$a1=newA();
$p=newPerson();
----------------------- 页面 5-----------------------
$p->setA($a1);
echo$p->getA()->name;
?>
再次提示
在PHP5中,指向对象的变量是引用变量。在这个变量里面存储的是所指向对象的内存地址。
引用变量传值时,传递的是这个对象的指向。而非复制这个对 象。这与其它类型赋值有所
不同。
PHP
PHP
PPHHPP类实例教程(五):对象的比较
在PHP中有 =
赋值符号、== 等于符号和 === 全等于符号, 这些符号代表什么意思?当使
用比较操作符(==)时,对象以一种很简单的规则比较:当两个对象有相同的属性和值,
属于同一个类且被定义在相同的命名空间 中,则两个对象相等。等于符号比较对象时,比
较对象是否有相同的属性和值。注意:== 比较两个不同的对象的时候,可能相等也可能不
等。
classPerson
{
public$name="NickName";
}
//分别创建两个对象
$p=newPerson();
$p1=newPerson();
//比较对象
if($p==$p1){
echo"\\$p和\\$p1内容一致";
}else{
echo"\\$p和\\$p1内容不一致";
}
echo"
";
$p->name="Tom";
if($p==$p1){
echo"\\$p和\\$p1内容一 致";
}else{
echo"\\$p和\\$p1内容不 一致";
}
?>
使用 == 符号比较两个对象,比较的仅仅是两个对象的内容是否一致。当使用全等符(===)
时,当且仅当两个对象指向相同类(在某一特定的命名空间中)的同一个对象时才相等。
是否在是同一个对象,两边指向的对象是否有同样的内存地址。
classPerson
{
public$name="NickName";
----------------------- 页面 6-----------------------
}
//分别创建两个对象
$p=newPerson();
$p1=newPerson();
//比较两个对象
if($p===$p1){
echo"\\$p和\\$p1是一个对象";
}else{
echo"\\$p和\\$p1不是一个对象";
}
echo"
";
$p->name="Tom";
if($p===$p1){
echo"\\$p和\\$p1是一个 对象";
}else{
echo"\\$p和\\$p1不是一 个对象";
}
?>
结果 === 比较的是两个变量是否一个对象。
一个等于符号(=)表示赋值,是赋值计算。如果将对象赋予变量,是指变量将指向这个对
象。
classPerson
{
public$name="NickName";
}
$p=newPerson();
$p1=newPerson();
$p2=$p1;//变量$p2指向$p1 指向的对象
if($p2===$p1){
echo"\\$p2和\\$p1指向一个对象";
}else{
echo"\\$p2和\\$p1不指向一个对象";
}
echo"
";
$p=$p1;//变量$p指向$p1指 向的对象
if($p===$p1){
echo"\\$p和\\$p1指向一 个对象";
}else{
echo"\\$p2和\\$p1不指向一个对象";
}
?>
PHP
PHP
PPHHPP类实例教程(六):构造函数
----------------------- 页面 7-----------------------
构造方法又称为构造函数,是对象被创建时自动调用的方法,用来完成类初始化的工作。
构造函数和其它函数一样,可以传递参数,可以设定参数默认值。构造函数可以调用属性,
可以调用方法。构造函数可以被其它方法显式调用。
在PHP4 中使用与类名同名的方法为构造函数。在PHP5中依然支持了这种方式,但不建
议再使用这种方式。
classPerson{
private$name;
publicfunction__construct($name){
$this->name=$name;
echo"在类被初始化的时候,这里的代码将会运行
";
echo"\\$nameis$this->name
";
}
}
newPerson("tom");
newPerson("jack");
?>
PHP PHP
PHP PHP
PPHHPP类实例教程(七):析构函数与PPHHPP的
垃圾回收
析构函数:当某个对象成为垃圾或者当对象被显式销毁时执行。
GC(GarbageCollector)
GC(GarbageCollector)
GGCC((GGaarrbbaaggeeCCoolllleeccttoorr))
在PHP中,没有任何变量指向这个对象时,这个对象就成为垃圾。PHP会将其在内存中销
毁。这是PHP的GC(GarbageCollector)垃圾处理机制,防止内存溢出。当一个PHP线程结
束时,当前占用的所有内存空间都会被销毁,当前程序中的所有对象同样被销毁。
__destruct() 析构函数,是在垃圾对象被回收时执行。
析构函数也可以被显式调用,但不要这样去做。
析构函数是由系统自动调用的,不要在程序中调用一个对象的析构函数。
析构函数不能带有参数。
程序结束前,所有对象被销毁。析构函数被调用了。
classPerson{
publicfunction__destruct(){
echo"
析构函数在这里执行";
echo"
这里一般用来放置,关闭数据库,关闭文件等等收尾工作。";
}
}
$p=newPerson();
for($i=0;$i<5;$i++){
echo"
$i";
}
//我们在这里看到,在PHP程序结束前,对象被销毁了。
----------------------- 页面 8-----------------------
?>
当对象没有指向时,对象被销毁。
classPerson{
publicfunction__destruct(){
echo"
析构函数在这里执行";
echo"
这里一般用来放置,关闭数据库,关闭文件等等收尾工作。";
}
}
$p=newPerson();
$p=null;
//我们在这里看到,析构函数在这里被执行了。
for($i=0;$i<5;$i++){
echo"
$i";
}
?>
我们将$p设置为空或者第11行赋予$p一个字符串,这样$p之前指向的对象就成为了垃圾对
象。PHP将这个对象垃圾销毁。
unset
unset
uunnsseett变量
classPerson{
publicfunction__destruct(){
echo"
析构函数在这里执行
";
}
}
$p=newPerson();
$p1=$p;//设定新引用变量$p1也 指向这个对象
unset($p);
echo"是否看到\\$p被销毁, 对象也被销毁呢?";
for($i=0;$i<5;$i++){
echo"
$i";
}
unset($p1);
echo"我们看到这里,析构函数被执行了";
?>
unset一个引用变量时,unset 销毁的是指向对象的变量,而不是这个对象。
PHP
PHP
PPHHPP类实例教程(八):类的继承
继承是面向对象
最重要的特点之一,就是可以实现对类的复用。
通过“继承”一个现有的类,可以使用已经定义的类中的方法和属性。
继承而产生的类叫做子类。
被继承的类,叫做父类,也被成为超类。
----------------------- 页面 9-----------------------
PHP是单继承的,一个类只可以继承一个父类,但一个父类却可以被多个子类所继承。
从子类的角度看,它“ 继承(inherit , extends)”自父类;而从父类的角度看,它“派生(derive)”
子类。它们指的都是同一个动作,只是角度不同而已。
子类不能继承父类的私有属性和私有方法。
在PHP5中类的方法可以被继承,类的构造函数也能被继承。
继承的简单例子
我们分析自然界中的关系,动物类与犬类的关系。
classAnimal
{
private$weight;
publicfunctiongetWeight(){
return$this->weight;
}
publicfunctionsetWeight($W){
$this->weight=$W;
}
}
classDogextendsAnimal
{
}
?>
当我们实例化animal类的子类Dog类时,父类的方法setWeight() 和getWeight() 被继承。
我们可以直接调用父类的方法设置其属性$weight,取得其属性$weight 。
……….
$myDog=newDog();
$myDog->setWeight(20);
echo"Mydog'sweightis".$myDog->getWeight()."
";
$myDog->Bark();
?>
构造函数的继承
有些资料上说PHP5的构造函数不被继承。演示的结果证明,PHP5的构造函数被继承了。当
子类Dog1被实例化时,继承的构造函数被调用了,屏幕 上显示了一句“IamanAnimal.”。
classAnimal
{
public$legNum=0;
publicfunction__construct(){
$this->legNum=4;
echo"Iamananimal
";
----------------------- 页面 10-----------------------
}
}
classDog1extendsAnimal
{
}
$dog1=newDog1();
echo"
";
echo "legNumis".$dog1->legNum;
/*
实例化子类时,构造函数被调用了。
*/
?>
私有变量和方法不被继承
PHP private,
PHP private,
PPHHPP类实例教程(九):访问控制 pprriivvaattee,,
protected,public
protected,public
pprrootteecctteedd,,ppuubblliicc
在PHP5中,可以在类的属性和方法前面加上一个修饰符(modifier),来对类进行一些访问
上的控制。
Public(公开): 可以自由的在类的内部外部读取、修改。
Private(私有): 只能在这个当前类的内部读取、修改。
Protected(受保护):能够在这个类和类的子类中读取和修改。
Private
Private
PPrriivvaattee的访问权限
private 不能直接被外部调用,只能由当前对象调用
。前面介绍过关于封装的内容这里不再
重复。比如你可以借钱给别人,但不希望别人知道你钱包里面有多少钱。我们把它用private
隐藏起来。
classMoney
{
private$mymoney=1000;//我有点钱数
//借出钱的方法
publicfunctionloan($num){
if($this->mymoney>=$num){
$this->mymoney=$this->mymoney-$num;
echo"好的,这里借给 你$num 元,可是我也不多了。
";
}else{
echo"我无法借 $num 元给你,我没有这么多钱。
";
}
}
}
$mon=newMoney();
$mon->loan(300);
----------------------- 页面 11-----------------------
$mon->loan(600);
$mon->loan(400);
echo$mon->mymoney;
// 这个地方会抛出异常,私有变量不能被外界访问
?>
Protected
Protected
PPrrootteecctteedd的访问权限
protected 修饰的属性和方法只能被子类调用。外界无法调用。
classMoney
{
protected$mymoney=1000;//我有点钱数
//借出钱的方法
publicfunctionloan($num){
if($this->mymoney>=$num){
$this->mymoney=$this->mymoney-$num;
echo"好的,这里借给你 $num 元,可是我也不多了。
";
}else{
echo"我无法借$num 元给你,我没有这么多钱。
";
}
}
}
classSMoneyextendsMoney
{
publicfunctiongetMoney(){
return$this->mymoney;
}
}
$mon=newSMoney();
$mon->loan(900);//借钱
echo"老婆,这里我还有...".$mon->getMoney()."元"; //其他人不允许访问,
?>
Public
Public
PPuubblliicc的访问权限
数据的隐藏和封装是能够帮助我们保护数据的安全性。Public 修饰的属性和方法,可以被无
的调用。嘿。你的钱,不安全了。
classMoney
{
public$mymoney=1000;//我有点钱数
//借出钱的方法
publicfunctionloan($num){
if($this->mymoney>=$num){
$this->mymoney=$this->mymoney-$num;
----------------------- 页面 12-----------------------
echo"好的,这里借给你 $num 元,可是我也不多了。
";
}else{
echo"我无法借$num 元给你,我没有这么多钱。
";
}
}
}
$mon=newMoney();
$mon->mymoney=$mon->mymoney-5000;
echo"我现在只有".$mon->mymoney;
echo"
钱哪里去了,我也不知道。";
?>
PHP override
PHP override
PPHHPP类实例教程(十):类的重写(oovveerrrriiddee)
如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖
(override),也称为方法的重写。
当 对父
类的方法进行重写时,子类中的方法必须和父类中对应的方法具有相同的方法名称,
在PHP5中不输入参数类型、参数数量和返回值类型。(这点和 JAVA不同)
子类中的覆盖方法不能使用比父类中被覆盖方法更严格的访问权限。
声明方法时,如果不定义访问权限。默认权限为 public。
先设置一个父类,这个父类是“Dog”类,这个类描述了dog的特性。Dog有2个眼睛,会跑,
会叫。就这样描述先。我养了一直狗,是只小狗,符合Dog类的特性,但有所不同。我的小
狗有名字,我的小狗太小了,不会大声的叫,只会哼哼。 我们用继承的概念去实现这个设
计。
//狗有两只眼睛,会汪汪叫,会跑
class Dog
{
protected $eyeNumber=2;//
//返回封装的属性方法
publicfunctiongetEyeNumber(){
return$this->eyeNumber;
}
//狗会叫
publicfunction yaff(){
return "Dogyaff,wang..wang..";
}
//狗会跑
publicfunction run(){
return "Dogrun..running...";
}
}
$dog=newDog();
echo"doghave".$dog->getEyeNumber()."eyes.
";
----------------------- 页面 13-----------------------
echo$dog->yaff()."
".$dog->run();
echo "
";
//这是我的小狗,叫"狗狗
$a";
echo"
";
echo"\\$this->a 是属性$this->a";
}
}
$a=newA(); //这里的$a可不是类中的任何变量
$a->printInt(88);
?>
----------------------- 页面 14-----------------------
$this
$this
用$$tthhiiss调用对象中的其它方法
classMath
{
//两个数值比较大小
publicfunctionMax($a,$b){
return$a>$b?$a:$b;
}
//三个数值比较大小
publicfunctionMax3($a,$b,$c){
$a=$this->Max($a,$b); //调用类中的其它方法
return$this->Max($a,$c);
}
}
$math=newMath();
echo"最大值是".$math->Max3(99,100,88);
?>
$this
$this
使用$$tthhiiss调用构造函数
调用构造函数和析构函数的方法一致。
classA
{
private$a=0;
publicfunction__construct(){
$this->a=$this->a+1;
}
publicfunctiondoSomeThing(){
$this->__construct();
return$this->a;
}
}
$a=newA();// 这里的$a 可不是类中的任何一个变量了
echo"现在\\$a 的值是".$a->doSomeThing();
?>
$this
$this
$$tthhiiss 到底指的什么?
$this 就是指当前对象,我们甚至可以返回这个对象使用$this。
classA
{
publicfunction getASelf(){
return$this;
----------------------- 页面 15-----------------------
}
publicfunction__toString(){
return"这是类A的实例";
}
}
$a=newA(); //创建A的实例
$b=$a->getASelf();//调用方法返回当前实例
echo$a; //打印对象会调用它 的__toString方法
?>
$this
$this
通过 $$tthhiiss 传递对象
在这个例子中,我们写一个根据不同的年龄发不同工资的类。我们设置处理年龄和工资的业
务模型为一个的类。
classUser
{
private$age;
private$sal;
private$payoff; //声明全局属性
//构造函数,中创建Payoff的对象
publicfunction__construct(){
$this->payoff=newPayoff();
}
publicfunctiongetAge(){
return$this->age;
}
publicfunctionsetAge($age){
$this->age=$age;
}
// 获得工资
publicfunctiongetSal(){
$this->sal= $this->payoff->figure($this);
return$this->sal;
}
}
//这是对应工资与年龄关系的类.
classPayoff
{
publicfunctionfigure($a){
$sal=0;
$age=$a->getAge();
if($age>80||$age<16){
$sal=0;
}elseif($age>50){
----------------------- 页面 16-----------------------
$sal=1000;
}else{
$sal=800;
}
return$sal;
}
}
//实例化User
$user=newUser();
$user->setAge(55);
echo$user->getAge()."age,hissalis".$user->getSal();
echo"
";
$user->setAge(20);
echo$user->getAge()."age,hissalis".$user->getSal();
echo"
";
$user->setAge(-20);
echo$user->getAge()."age,hissalis".$user->getSal();
echo"
";
$user->setAge(150);
echo$user->getAge()."age,hissalis".$user->getSal();
?>
PHP parent::
PHP parent::
PPHHPP类实例教程(十二):类中ppaarreenntt::::关键
字
PHP5中使用parent::来引用父类的方法。 parent:: 可用于调用父类中定义的成员方法。
parent::的追溯不仅于直接父类。
parent::
parent::
通过ppaarreenntt::::调用父类方法
classemployee
{
protected $sal=3000;
publicfunctiongetSal(){
$this->sal=$this->sal+1200;
return$this->sal;
}
}
classManagerextendsemployee
{
//如果想让经理在员工工资的基础上多发1500元
//必须先调用父类的getSal()方法
publicfunctiongetSal(){
----------------------- 页面 17-----------------------
parent::getSal(); // 这里调用了父类的方法
$this->sal=$this->sal+1500;
return$this->sal;
}
}
$emp=newemployee();
echo"普通员工的工资是".$emp->getSal();
echo"
";
$manager=newManager();
echo"经理的工资是:".$manager->getSal();
?>
private
private
父类的pprriivvaattee属性
Private属性是不能被继承的,如果父类有私有的属性。那么父类的方法只为父类的私有属
性服务。
classemployee
{
private $sal=3000;
//protected$sal=3000;
publicfunctiongetSal(){
return$this->sal;
}
}
classManagerextendsemployee
{
protected $sal=5000;
publicfunctiongetParentSal(){
//这里返回的是父类的private属性
returnparent::getSal();
}
}
$manager=newManager();
echo"PHP".phpversion()."
";
echo$manager->getSal();
echo"
";
echo"parent's\\$sal".$manager->getParentSal();
?>
如果父类中的属性被子类重写了。注意 第5行的属性定义变成protected。那么两次的输出是
不一样的,如果你学过java,你会觉得这一切都是很难理解的。在Java中当子类被创建时,
父类的属性和方法在内存中都被创建,甚至构造函数也要被调用。PHP5不是这样,PHP5调
用父类用的是parent:: 而不是 parent-> ,这足以说明PHP5不想在内存中让父类也被创建。
PHP5想让继承变的比Java更简单。适应下就好。
----------------------- 页面 18-----------
------------
PHP Static
PHP Static
PPHHPP类实例教程(十三):SSttaattiicc的用法
static关键字用来修饰属性、方法,称这些属性、方法为静态属性、静态方法。
static关键字声明一个属性或方法是和类相关的,而不是和类的某个特定的实例相关,因此,
这类属性或方法也称为“类属性”或“类方法”
如果访问控制权限允许,可不必创建该类对象而直接使用类名加两个冒号“::”调用。
static关键字可以用来修饰变量、方法。
不经过实例化,就可以直接访问类中static的属性和static的方法。
static 的属性和方法,只能访问static的属性和方法,不能类访问非静态的属性和方法。因
为静态属性和方法被创建时,可能还没有任何这个类的实例可以被调用。
static的属性,在内存中只有一份,为所有的实例共用。
使用self:: 关键字访问当前类的静态成员。
一个类的所有实例,共用类中的静态属性。
也就是说,在内存中即使有多个实例,静态的属性也只有一份。
下面例子中的设置了一个计数器$count属性,设置private 和static 修饰。
这样,外界并不能直接访问$count属性。而程序运行的结果我们也看到多个实例在使用同一
个静态的$count 属性。
classuser
{
privatestatic$count=0;//记录所有用户的登录情况.
publicfunction__construct(){
self::$count=self::$count+1;
}
publicfunctiongetCount(){
returnself::$count;
}
publicfunction__destruct(){
self::$count=self::$count-1;
}
}
$user1=newuser();
$user2=newuser();
$user3=newuser();
echo"nowherehave".$user1->getCount()."user";
echo"
";
unset($user3);
echo"nowherehave".$user1->getCount()."user";
?>
静态属性直接调用
静态属性不需要实例化就可以直接使用,在类还没有创建时就可以直接使用。
使用的方式是: 类名::静态属性名
----------------------- 页面 19-----------------------
classMath
{
publicstatic$pi=3.14;
}
// 求一个半径3的园的面积。
$r=3;
echo"半径是$r 的面积是
";
echoMath::$pi*$r*$r;
echo"
";
//这里我觉得3.14 不够精确,我把它设置的更精确。
Math::$pi=3.1415926535793;
echo"半径是$r 的面积是
";
echoMath::$pi*$r*$r;
?>
类没有创建,静态属性就可以直接使用。那静态属性在什么时候在内存中被创建? 在PHP
中没有看到相关的资料。引用Java中的概念,来解释应该也具有通用性。静态属性和方法,
在类被调用时创建。
静态方法
静态方法不需要所在类被实例化就
可以直接使用。
使用的方式是类名::静态方法名
下面我们继续写这个Math类,用来进行数学计算。我们设计一个方法用来算出其中的最大
值。既然是数算,我们也没有必要去实例化这个类,如果这个方法 可以拿过来就用就
方便多了。我们这只是为了演示static方法而设计的这个类。在PHP提供了 max() 函数比
较数值。
classMath
{
publicstaticfunctionMax($num1,$num2){
return$num1>$num2?$num1:$num2;
}
}
$a=99;
$b=88;
echo"显示$a 和$b 中的最大值是";
echo"
";
echoMath::Max($a,$b);
echo"
";
echo"
";
echo"
";
$a=99;
$b=100;
echo"显示$a 和$b 中的最大值是";
echo"
";
----------------------- 页面 20-----------------------
echoMath::Max($a,$b);
?>
静态方法如何调用静态方法
第一个例子,一个静态方法调用其它静态方法时,使用self::
// 实现最大值比较的Math类。
classMath
{
publicstaticfunctionMax($num1,$num2){
return$num1>$num2?$num1:$num2;
}
publicstaticfunctionMax3($num1,$num2,$num3){
$num1=self::Max($num1,$num2);
$num2=self::Max($num2,$num3);
$num1=self::Max($num1,$num2);
return$num1;
}
}
$a=99;
$b=77;
$c=88;
echo"显示$a$b$c 中的最大值是";
echo"
";
echoMath::Max3($a,$b,$c);
?>
静态方法调用静态属性
使用self:: 调用本类的静态属性。
//
classCircle
{
publicstatic$pi=3.14;
publicstaticfunctioncircleAcreage($r){
return$r*$r*self::$pi;
}
}
$r=3;
echo" 半径 $r 的圆的面积是".Circle::circleAcreage($r);
?>
静态方法不能调用非静态属性。不能使用self::调用非静态属性。
----------------------- 页面 21-----------------------
// 这个方式是错误的
classCircle
{
public$pi=3.14;
publicstaticfunctioncircleAcreage($r){
return$r*$r*self::pi;
}
}
$r=3;
echo" 半径 $r 的圆的面积是".Circle::circleAcreage($r);
?>
也不能使用 $this 获取非静态属性的值。
静态方法调用非静态方法
PHP5中,在静态方法中不能使用 $this 标识调用非静态方法。
// 实现最大值比较的Math类。
classMath
{
publicfunctionMax($num1,$num2){
echo"bad
";
return$num1>$num2?$num1:$num2;
}
publicstaticfunctionMax3($num1,$num2,$num3){
$num1=$this->Max($num1,$num2);
$num2=$this->Max($num2,$num3);
$num1=$this->Max($num1,$num2);
return$num1;
}
}
$a=99;
$b=77;
$c=188;
echo"显示$a $b$c 中的最大值是";
echo"
";
echoMath::Max3($a,$b,$c); //同样
的这个会报错
?>
当一个类中有非静态方法被self:: 调用时,系统会自动将这个方法转换为静态方法。
// 实现最大值比较的Math类。
classMath
{
publicfunctionMax($num1,$num2){
return$num1>$num2?$num1:$num2;
----------------------- 页面 22-----------------------
}
publicstaticfunctionMax3($num1,$num2,$num3){
$num1=self::Max($num1,$num2);
$num2=self::Max($num2,$num3);
$num1=self::Max($num1,$num2);
return$num1;
}
}
$a=99;
$b=77;
$c=188;
echo"显示$a $b$c 中的最大值是";
echo"
";
echoMath::Max3($a,$b,$c);
?>
PHP
PHP
PPHHPP类实例教程(十四):设计模式之单件模
式
单件模式要解决的问题就是“如何让这个类只有一个实例”。
我们的web应用中,大量使用了数据库连接,如果反复建立与数据库的连接必然消耗更多
的系统资源。
我们如何解决这个问题,建立唯一的数据库连接是必要的方式。
我们又如何知道与这个数据库的连接是否已经建立? 还是需要现在建立?
单件模式可以解决这个问题。
先假设我们需要一个类完成在内存中只有一份的功能,我们该如何做呢?
我们一步一步的使用前面学过的知识来写一个单件的例子。
1
1
问题11:
前面学过,每次用new 类名的方式,就可以创建一个对象。
我们必须禁止外部程序用 new 类名的方式来创建多个实例。
解决办法:
我们将构造函数设置成private ,让构造函数只能在内部被调用,而外部不能调用。
这样,这个类就不能被外部用 new 的方式建立多个实例了。
不能被外部用new实例化的类。
classA
{
privatefunction__construct(){
}
}
?>
----------------------- 页面 23-----------------------
2
2
问题22:
我们已经禁止外部用new实例化这个类,我们改如何让用户访问这个类呢?前门堵了,我们
需要给用户留个后门。
解决办法:
static 修饰的方法,可以不经实例化一个类就可以直接访问这个方法。
后门就在这里。
classA
{
privatefunction__construct(){
}
staticfunctiongetClassA(){
return"这里是后门,可以通过这里进入这个类的内部";
}
}
echoA::getClassA();
?>
3
3
问题33:
虽然我们已经进入类内部,但我们要的是这个类的唯一实例?
先不管别的,我们先需要一个实例。
通过这个static的方法返回这个实例,如何做呢?
解决办法:
private的构造函数,不能被外部实例化。
但是我们已经成功潜入类的内部了(间谍?007?),我们在内部当然可以调用private的方
法创建对象。
我们这样做看看。
下面的例子我们确实返回了A类的实例,但注意两次执行返回的不是同一个实例。
classA
{
privatefunction__construct(){
}
staticfunctiongetClassA(){
$a=newA();
return$a;
}
}
$a1=A::getClassA();
$a2=A::getClassA();
echo"\\$a1的类是".get_class($a1).
自Math类
classSuperMathextendsMath
{
}
//执行会出错,final类不能被继承。
?>
final
final
ffiinnaall方法不能被重写
如果不希望类中的某个方法被子类重写,我们可以设置这个方法为final方法,只需要在这
个方法前加上final修饰符。如果这个方法被子类重写, 将会出现错误。
//声明一个final类Math
classMath
{
publicstatic$pi=3.14;
publicfunction__toString(){
return"这是Math类。";
}
publicfinalfunctionmax($a,$b)
return$a>$b?$a:$b;
----------------------- 页面 26-----------------------
}
}
//声明类SuperMath 继承自Math类
classSuperMathextendsMath
{
publicfinalfunctionmax($a,$b){
}
}
//执行会出错,final方法不能被重写。
?>
PHP PHP5
PHP PHP5
PPHHPP类实例教程(十六):PPHHPP55中的常量
在PHP5类中继续使用cons修饰常量。我们使用const定义一个常量,定义的这个常量不能
被改变。在PHP5中const定义的常 量与定义变量的方法不同,不需要加$修饰符。constPI =
3.14;这样就可以。
而使用const 定义的常量名称一般都大写,这是一个约定,在任何语言中都是这样。
如果定义的常量由多个单词组成,使用 _ 连接,这也是约定。
比如, MAX_MUMBER 这样的命名方式。一个良好的命名方式,是程序员必须注意的。
类中的常量使用起来类似静态变量,不同点只是它的值不能被改变。我们使用类名::常量名
来调用这个常量。
//声明一个final类Math
classMath
{
constPI=3.14;
publicfunction__construct(){
return"这是Math类";
}
//这里写了一个算圆面积的方法,使用了Const常量,
//注意使用的方法,类似于静态变量。
publicfinalfunctionarea($r){
return$r*$r*self::PI;
}
publicfinalfunctionmax($a,$b){
return$a>$b?$a:$b;
}
}
echoMath::PI;
?>
尝试为const定义的常量赋值,将会出现错误。
----------------------- 页面 27-----------------------
//说明一个final类Math
classMath
{
constPI=3.14;
publicfunction__toString(){
return"这是一个Math类";
}
//这里写了一个算圆面积的方法,使用了Const常量,
//注意使用的方法,类似与静态变量。
publicfinalfunctionarea($r){
return$r*$r*self::PI;
}
publicfinalfunctionmax($a,$b){
return$a>$b?$a:$b;
}
publicfunctionsetPI($a){
self::PI=3.1415;
}
}
echoMath::PI;
?>
PHP abstract
PHP
abstract
PPHHPP类实例教程(十七):aabbssttrraacctt类和
abstract
abstract
aabbssttrraacctt方法
可以使用abstract来修饰一个类或者方法。
用abstract修饰的类表示这个类是一个抽象类,用abstract修饰的方法表示这个方法是一个
抽象方法。
抽象类不能被实例化。
抽象方法是只有方法声明,而没有方法的实现内容。
abstract
abstract
aabbssttrraacctt 抽象类
可以使用abstract来修饰一个类。
用abstract修饰的类表示这个类是一个抽象类。
抽象类不能被实例化。
这是一个简单抽象的方法,如果它被直接实例化,系统会报错。
//定义一个抽象类
abstractclassUser
{
publicfunction__toString(){
returnget_class($this);
----------------------- 页面 28-----------------------
}
}
//实例化这个类会出现错误
echonewUser();
?>
下面例子的 NormalUser 继承自User类,就可以被实例化了。
//定义一个抽象类
abstractclassUser
{
publicfunction__toString(){
returnget_class($this);
}
}
//实例化这个类会出现错误
echonewUser();
classNormalUserextendsUser
{
}
$a=newNormalUser();
echo"这个类".$a."的实例";
?>
单独设置一个抽象类是没有意义的,只有有了抽象方法,抽象类才有了血肉。下面介绍抽象
方法。
abstract
abstract
aabbssttrraacctt 抽象方法
用abstract修饰的类表示这个方法是一个抽象方法。
抽象方法,只有方法的声明部分,没有方法体。
抽象方法没有 {} ,而采用 ; 结束。
一个类中,只要有一个抽象方法,这个类必须被声明为抽象类。
抽象方法在子类中必须被重写。
下面是一个抽象类,其中有两个抽象方法,分别是setSal() 和 getSal()。用来取回 $sal 员
工的工资。
abstractclassUser
{
protected$sal=0;
//这里定义的抽象方法。
//注意抽象方法没有方法体,而且方法结束使用; 号。
abstractfunctiongetSal();
abstractfunctionsetSal();
//定义它的__tostring方法
publicfunction__toString(){
returnget_class($this);
----------------------- 页面 29-----------------------
}
}
?>
既然User类不能被直接继承,我们写一个NormalUser类继承自User类。当我们写成如下
代码时,系统会报错。 这个错误告诉我们,在 User类中有两个抽象方法,我们必须在子
类中重写这两个方法。
abstractclassUser
{
protected$sal=0;
//这里定义的抽象方法。
//注意抽象方法没有方法体,而且方法结束使用; 号。
abstractfunctiongetSal();
abstractfunctions
etSal();
//定义它的__tostring方法
publicfunction__toString(){
returnget_class($this);
}
}
classNormalUserextendsUser
{
}
?>
下面例子,重写了这两个方法,虽然方法体里面 {} 的内容是空的,也算重写了这个方法。
注意看重写方法的参数名称,这里只要参数数量一致就可以,不要求参数的名称必须一致。
abstractclassUser
{
protected$sal=0;
//这里定义的抽象方法。
//注意抽象方法没有方法体,而且方法结束使用;号。
abstractfunctiongetSal();
abstractfunctionsetSal();
//定义它的__tostring方法
publicfunction__toString(){
returnget_class($this);
}
}
classNormalUserextendsUser
{
functiongetSal(){
}
functionsetSal($sal){
}
----------------------- 页面 30-----------------------
}
//这样就不会出错了。
?>
下面19-21行,三种写重写的方式都会报错。
19行,缺少参数。
20行,参数又多了。
21行,参数类型不对。(这种写法在以后章节介绍)
一个类中,如果有一个抽象方法,这个类必须被声明为抽象类。
下面这个类不是抽象类,其中定义了一个抽象方法,会报错。
classUser
{
protected$sal=0;
//这里定义的抽象方法。
//注意抽象方法没有方法体,而且方法结束使用;号。
abstractfunctiongetSal();
abstractfunctionsetSal();
//定义它的__tostring方法
publicfunction__toString(){
returnget_class($this);
}
}
//这个类中有两个抽象方法,如果这个类不是抽象的。会报错
?>
抽象类继承抽象类
抽象类继承另外一个抽象类时,不用重写其中的抽象方法。
抽象类中,不能重写抽象父类的抽象方法。
这样的用法,可以理解为对抽象类的扩展
下面的例子,演示了一个抽象类继承自另外一个抽象类时,不需要重写其中的抽象方法。
abstractclassUser
{
protected$sal=0;
abstractfunctiongetSal();
abstractfunctionsetSal($sal);
}
abstractclassVipUserextendsUser
{
}
?>
抽象类在被继承后,其中的抽象方法不能被重写。
如果发生重写,系统会报错。
----------------------- 页面 31-----------------------
abstractclassUser
{
protected$sal=0;
abstractfunctiongetSal();
abstractfunctionsetSal($sal);
}
abstractclassVipUserextendsUser
{
abstractfunctionsetSal();
}
?>
抽象类继承抽象类,目的对抽象类的扩展。
abstractclassUser
{
protected$sal=0;
abstractfunctiongetSal();
abstractfunctionsetSal($sal);
}
abstractclassVipUserextends
User
{
protected$commision=0;
abstractfunctiongetCommision();
abstractfunctionsetCommision();
}
?>
在PHP5.1中,抽象类中支持静态抽象方法。下面这个例子,看到静态抽象方法可以声明。
实现这个方法时,必须是静态的方法。
静态抽象方法
在PHP5.1中,抽象类中支持静态抽象方法。下面这个例子,看到静态抽象方法可以声明。
实现这个方法时,必须是静态的方法。
abstractclassUser
{
protectedstatic $sal=0;
staticabstractfunctiongetSal();
staticabstractfunctionsetSal($sal);
}
classVipUserextendsUser
{
staticfunctiongetSal(){
returnself::$sal;
}
----------------------- 页面 32-----------------------
staticfunctionsetSal($sal){
self::$sal=$sal;
}
}
VipUser::setSal(100);
echo"yousalis".VipUser::getSal();
?>
//这里的抽象方法好像没有问题
PHP
PHP
PPHHPP类实例教程(十八):设计模式之模版模
式
抽象类的应用就是典型的模版模式,先声明一个不能被实例化的模版,在子类中去依照模版
实现具体的应用。
模版模式实例
我们写这样一个应用:
银行计算利息,都是利率乘以本金和存款时间,但各种存款方式计算利率的方式不同,所以,
在账户这个类的相关方法里,只搭出算法的骨架,但不具体实 现。具体实现由各个子类来
完成。
//程序设计模式的模块部分
abstractclassLoadAccount
{
//利息,本金
protected$interest,$fund;
publicfunctioncalculateInterest(){
//取得利率
$this->interest=getInterestRate();
//用于计算利息的算法:本金*利率,但是利率的算法实 现并没有在这个类中实现
$this->interest=$this->getFund()*$this->getInterstRate();
return$this->interest;
}
privatefunctiongetFund(){
return$this->fund;
}
//.......
/*
* 不同类型的存款的利率不同,因此,
* 不在这个父类中实现率的计算方法,
* 而将他推迟到子类中实现
*/
protectedabstractfunctiongetInterstRate();
}
?>
----------------------- 页面 33-----------------------
所有和计算利息的类都继承自这个类,而且必须实现其中的 getInterestRate() 方法,这种用
法就是模版模式
PHP PHP
PHP PHP
PPHHPP类实例教程(十九):PPHHPP类接口的定义
与规范
接口(interface)是抽象方法和静态常量定义的集合。
接口是一种特殊的抽象类,这种抽象类中只包含抽象方法和静态常量。
接口中没有其它类型的内容。
接口的定义
我们先写接口的定义,后面几节再介绍接口的意义。
下面的例子是接口的一个简单写法。
interface 接口名
{
}
?>
下面的例子定义了一个接口 User ,这个接口中有两个抽象方法,getName() 和setName()。
能看到接口的写法和类很相似。
interfaceUser
{
functionsetName($name);
functiongetName();
}
?>
接口中的抽象方法
注意,在接口中只能有抽象方法。如果在接口中出现了非抽象方法,会报错如下:Interface
functionUser::setName()cannotcontainbodyin……….
interfaceUser
{
functionsetName($name);
functiongetName(){} //这个地方是一个非抽象方法,会报错
}
?>
接口中抽象方法的修饰和访问权限
在接口中的抽象方法只能是public的,默认也是public权限。并且不能设置成private 或者
protected 类型。否则会报错如下: AccesstypeforinterfacemethodUser::setName()mustbe
omittedin—online— (在接口中,访问类型必须忽略。)
----------------------- 页面 34-----------------------
interfaceUser
{
functionsetName($name);
privatefunctiongetName();//不允许带修饰符,此处如果换成protected也会出错
}
?>
即使abstract 和 final 修饰符也不能修饰接口中的抽象的方法。
接口中的静态抽象方法
在接口中可以使用静态抽象方法。在PHP5.2中,不建议在抽象类中使用静态抽象方法。而
接口中依然保留了静态抽象方法。
interfaceUser
{
functionsetName($name);
staticfunctiongetName(){
}
}
?>
接口中的静态常量
在接口中可以定义静态常量。而且不用static修饰就是静态的常量。
interfaceUser
{
constMAX_GRADE=99; //此处不用声明,就是一个静态常量
functionsetName($name);
staticfunctiongetName(){
}
}
?>
PHP PHP
PHP PHP
PPHHPP类实例教程(二十):PPHHPP类接口的实现
接口
类实现接口要使用 implements 。类实现接口要实现其中的抽象方法。一个类可以实现多个
接口。
一个类可以使用 implements 实现接口,甚至可以实现多个接口。
大部分的书说,这样是为了实现PHP的多继承。为什么呢?
PHP5是单继承的,一个类只可以继承自一个父类。接口可以实现多个,这样就是多继承了。
这样说有些道理。但,既然接口里面的方法没有方法体,所谓的多继承又有什么意义?
接口的意义在于后面一节继续说的多态。
----------------------- 页面 35-----------------------
implements
implements
使用iim
immpplleemmeennttss实现接口
使用implements来实现一个接口。如果实现接口而没有实现其中的抽象方法,会报错如下。
interfaceUser
{
constMAX_GRADE=99; //此处不用声明,就是一个静态常量
functionsetName($name);
staticfunctiongetName(){
}
}
classNoumalUserimplementsUser
{
}
?>
Fatalerror: InterfacefunctionUser::getName() cannotcontainbodyinC:\\wamp\\www\t.phpon
line5 实现接口要实现方法。注意静态变量的使用。
interfaceUser
{
constMAX_GRADE=99; //此处不用声明,就是一个静态常量
functionsetName($name);
functiongetName();
}
//实现接口
classNoumalUserimplementsUser
{
private$name;
functiongetName(){
return$this->name;
}
functionsetName($_name){
$this->name=$_name;
}
}
$normalUser=newNoumalUser();//创建对象
$normalUser->setName("http://www.isstudy.com");
echo"URLis".$normalUser->getName();
echo"
";
echo"MAX_GRADEis".NoumalUser::MAX_GRADE; //静态常量
?>
实现多个接口
一个类可以实现多个接口。只要使用 , 号将多个接口链接起来就可以。
----------------------- 页面 36-----------------------
interfaceUser
{
constMAX_GRADE=99; //此处不用声明,就是一个静态常量
functionsetName($name);
functiongetName();
}
interfaceadministrator
{
functionsetBulletin($_bulletin);
}
//多个接口
classNoumalUserimplementsUser,administrator
{
private$name;
functiongetName(){
}
functionsetName($_name){
}
functionsetBulletin($_setBulletin){
}
}
?>
继承并实现接口
classStudent
{
protected$grade;
publicfunctiongetGrade(){
return$this->grade;
}
}
interface User
{
functiongetName();
functionsetName($_name);
}
//只有管理员可以设置公告
interfaceAdministrator
{
functionsetBulletin($_bulletin);
}
//为了节省版面,下面方法只写空的实现.不写具体内容了
----------------------- 页面 37-----------------------
classStudentAdminextendsStudentimplementsUser,Administrator
{
functiongetName(){
}
functionsetName($_name){
}
functionsetBulletin($_bulletin){
}
}
$s=newStudentAdmin();
echo$s->getGrade();
echo$s->getName();
echo$s->setBulletin(" 公告内容");
?>
PHP PHP
PHP PHP
PPHHPP类实例教程(二十一):PPHHPP类接口的继
承
一个接口可以继承自另外的接口。PHP5中的类是单继承,但是接口很特殊。一个接口可以
继承自多
个接口。
一个接口继承其它接口时候,直接继承父接口的静态常量属性和抽象方法。
在PHP5中,接口是可以继承自另外一个接口的。这样代码的重用更有效了。
要注意只有接口和接口之间使用 继承关键字extends。
类实现接口必须实现其抽象方法,使用实现关键字 implements。
接口实现继承
要注意只有接口和接口之间使用 继承关键字extends。
类实现接口必须实现其抽象方法,使用实现关键字 implements。
这个例子定义接口User,User有两个抽象方法getName和setName。又定义了接口VipUser,
继承自User接口,并增加了和 折扣相关的方法getDiscount。最后定义了类Vip ,实现了
VipUser接口。并实现了其中的三个方法。
interfaceUser
{
functiongetName();
functionsetName($_name);
}
interfaceVipUserextendsUser
{
functiongetDiscount();//此处添加了一个抽象的方法
}
classVipimplementsVipUser
{
private$name;
----------------------- 页面 38-----------------------
private$discount=0.8; //折扣变量
functiongetName(){
return$this->name;
}
functionsetName($_name){
$this->name=$_name;
}
functiongetDiscount(){
return$this->discount;
}
}
PHP
PHP
PPHHPP类实例教程(二十二):类型提示
PHP是弱类型语言,向方法传递参数时候也不太区分类型。这样的使用会引起很多的问题,
PHP开发者认为,这些问题应该是由代码书写者在书写代码时进行检验以避免。没有类型
提示很危险。
classNormalUser
{
/*
* 其它相关代码..省略........
*/
private$age;
publicfunctionsetAge($_age){
$this->age=$_age;
}
publicfunctiongetAge(){
return$this->age;
}
}
$normalUser=newNormalUser();
$normalUser->setAge("Iamtom");// 这里我们传输一个非数值
echo"ageis".$normalUser->getAge(); //注意输出结果不是我想要的类型
?>
原始类型的类型判
PHP中提供了一些函数,来判断数值的类型。我们可使用is_numeric()。判断是否是一个数
值或者可转换为数值的字符串。
其它相关的还有is_bool()、is_int()、is_float()、is_integer()、is_numeric()、 is_string()、is_array()
和 is_object()。
于是代码有了修改
----------------------- 页面 39-----------------------
classNormalUser
{
/*
* 其它相关代码..省略........
*/
private$age;
publicfunctionsetAge($_age){
if(is_numeric($_age)){
$this->age=$_age;
}
}
publicfunctiongetAge(){
return$this->age;
}
}
$normalUser=ne
wNormalUser();
$normalUser->setAge("Iamtom"); //这里我们传输一个非数值.
echo"ageis".$normalUser->getAge(); //看到这里的结果为空.
echo "
";
$normalUser->setAge("100");
echo"ageis".$normalUser->getAge(); // 这里就有了结果.
?>
向方法内传递对象
如果传递的参数是一个对象呢?
下面的代码用起来很正常。
classNOrmalUser
{
private$name;
functionsetName($_name){
$this->name=$_name;
}
functiongetName(){
return$this->name;
}
}
classUserAdmin
{
//这里定义的参数,第一个是User类的实例,第二个是要设置的名字
staticfunctionchangeName($_user,$_name){
$_user->setName($_name);
}
}
----------------------- 页面 40-----------------------
$normalUser=newNOrmalUser();
UserAdmin::changeName($normalUser,"tom");
echo"usernameis".$normalUser->getName();
?>
PHP PHP
PHP PHP
PPHHPP类实例教程(二十三):PPHHPP抽象类实现
接口
抽象类实现接口,可以不实现其中的抽象方法,而将抽象方法的实现交付给具体能被实
例化的类去处 理。
interfaceUser { functiongetName(); functionsetName($_name); } // 此处只是实现了一个接口的一个方法 abstractclassabatractNormalUserimplementsUser { protected$name; functiongetName(){ return$this->name; } } // 这里实现了接口的另外一个方法 classNormalUserextendsabatractNormalUser { functionsetName($_name){ $this->name=$_name; } } $normaluser=newNormalUser(); $normaluser->setName("tom"); echo"nameis".$normaluser->getName(); ?>
