PHP5.3的新特性(一):对象接口的变化
2011-12-15 13:41
337 查看
PHPV5和面向对象编程
2004年PHPV5发布,和PHPV4相比,它在面向对象编程(OOP)和设计方面有了巨大的进步,增加了一些必要的特性,如类的可见性、正确的构造函数与析构函数、类型提示和类反射API。PHP5为高级面向对象编程开启了方便之门,使得开发者可以更简单地实现各种设计模式,设计出更好的类和API。
在PHPV5.3中,继续大幅加强OOP能力,这些改进包括语法的进化和性能的改善等方面。首先让我们来看静态方法和属性相关的新特性。
改进后的静态方法与属性的处理方式
PHPV5中一个实用的新增特性是可以指定类的一个方法或属性为静态成员(PHPV4支持静态地访问类的方法和属性,但是无法指定它们是为静态访问而设计的)。静态访问在实现单例模式时非常有用,此时,类只存在一个实例。
PHPV5.3增加了若干特性,以加强对类的静态方法和属性的支持。首先,我们来分析新增的魔术方法:
__
PHPV5包含了若干个可以用于类内部的魔术方法。如果在类中定义了这些方法,它们可以提供特殊的功能,从而实现重载(允许一个方法接收不同类型的参数)和多态(允许不同数据类型使用相同的接口)功能。同时,它们也让PHP中的面向对象编程(OOP)和设计模式的实现变得更加简单。
在PHPV5.3中,新增了一个魔术方法:
Listing1.Exampleofusing
PHP代码
classFoo
{
publicstaticfunction__callStatic(
$name,
$args
)
{
echo"Calledmethod$namestatically";
}
publicfunction__call(
$name,
$args
)
{
echo"Calledmethod$name";
}
}
Foo::dog();//输出"Calledmethoddogstatically"
$foo=newFoo;
$foo->dog();//输出"Calledmethoddog"
需要注意,PHP要求
动态的静态调用
PHP中有一个实用的特性是变量的变量。它意味着你可以用一个变量的字符串值作为另外一个变量的名字。换句话说,你可以完成下面的功能。
Listing2.Variablevariables
PHP代码
x='y';
$$x='z';
echo$x;//输出'y'
echo$$x;//输出'z'
同样的概念可以用于函数,甚至类的成员函数,如下例所示。
Listing3.Variablefunctionandclassmethodnames
PHP代码
classDog
{
publicfunctionbark()
{
echo"Woof!";
}
}
$class='Dog'
$action='bark';
$x=new$class();//实例化类'Dog'
$x->$action();//输出"Woof!"
在PHPV5.3中增加了一个功能,静态调用中的类名可以通过一个变量来指定。由此引入了一些新的编程方法,如下所示。
Listing4.Variableclassnaming
PHP代码
classDog
{
publicstaticfunctionbark()
{
echo"Woof!";
}
}
$class='Dog';
$action='bark';
$class::$action();//输出"Woof!"
这个新增功能使得PHP中变量的变量这个特性成为一个完备特性,可用于各种环境。
接下来让我们关注另外一个更加实用的关于静态方法和属性方面的功能改善:静态调用的晚绑定。
静态调用的晚绑定(膘叔:是否叫后绑定或者延迟绑定较好?)
PHPV5.3之前一个令人恼火的事情是静态方法和属性的处理。到目前为止,静态引用,包括使用self或__CLASS__,都是在函数定义所在类的范围内解析。当继承一个类,并在子类中调用静态函数时,将会发生解析错误。PHPV5.3中新增的静态调用晚绑定特性解决了这个问题。为了更好的说明这个问题,我们创建如下一个包含静态方法的类。
Listing5.Class
PHP代码
classFoo
{
protectedstatic$name='Foo';
publicstaticfunctiontest()
{
returnself::$name;
}
}
然后继承这个类,并在子类中重定义$name属性。
Listing6.Childclass
PHP代码
classBarextendsFoo
{
protectedstatic$name='Bar';
}
最后进行一个静态调用。
Listing7.Staticmethodcall
这个调用的输出将是字符串
PHPV5.3通过使用static关键字,使得该引用可以在当前类中解析。将上面的类Foo改写为如下定义(译注:注意红色部分),输出将变为Bar。
Listing8.Usingthestatickeyword
PHP代码
classFoo
{
protectedstatic$name='Foo';
publicstaticfunctiontest()
{
returnstatic::$name;
}
}
classBarextendsFoo
{
protectedstatic$name='Bar';
}
echoBar::test();//输出'Bar'
需要注意的是,static关键字的这种用法在非静态上下文中无效。也就是说普通的继承规则对静态调用无效。static关键字将简单的去尝试在当前类中进行解析,而不是函数定义所在的类。这是一个需要我们注意的事情。
在分析了一些有关静态方法和属性方面的改善之后,我们来看看PHPV5中非常重要的部分:标准PHP库中新增的一些类。
标准PHP库
PHPV5中新增的标准PHP库是用于解决标准问题的一组类和接口。这些问题包括可迭代对象、数组对象和链表等。使用这些类和接口的好处是:它们是PHP的原生方法,比用PHP实现的效率要高。同时,它们使得许多PHP内置函数和语言结构可以直接使用这些对象,比如你可以通过foreach结构遍历一个实现了迭代器接口的对象。
PHPV5.3在SPL中增加了若干个类。如早前提到过的双向链表SplDoublyLinkedList。SPL中新增的栈和队列类:SplStack和SplQueue的实现中都使用了该类。
下面看一下如何使用
Listing9.Using
PHP代码
$stack=newSplStack();
//pushafewnewitemsonthestack
$stack->push('a');
$stack->push('b');
$stack->push('c');
//seehowmanyitemsareonthestack
echocount($stack);//returns3
//iterateovertheitemsinthestack
foreach($stackas$item)
echo"[$item],";
//theaboveoutputs:[c],,[a]
//popanitemoffthestack
echo$stack->pop();//returns'c'
//nowseehowmanyitemsareonthestack
echocount($stack);//returns2
另外新增的一个实用类是
[b]Listing10.
PHP代码
$array=newSplFixedArray(3);
$array[0]='dog';
$array[1]='cat';
$array[2]='bird';
$a->setSize(4);//increasethesizeonthefly
$array[3]='mouse';
foreach($arrayas$value)
echo"[$value],";
Output:
[dog],[cat],[bird],[mouse]
此外,还增加了两个迭代器类:
另外一个变化是SPL在PHPV5.3中将强制启用。以前的PHPV5版本,你可以在编译的时候禁止SPL,但是这个选项现在没有了。
SPL的改善提高了PHP的易用性,并实现了数据结构如双向链表、栈、堆和队列等。它们可以替换用户自己实现的这些数据结构,这样不但可以提高效率,而且还可以促进PHP函数和语言结构的整合。
讨论完SPL的改进之后,我们看看PHPV5.3如何通过采用循环垃圾回收技术来提高OOP的性能与内存消耗。
循环垃圾回收
PHP开发者经常碰到的一个性能瓶颈是垃圾回收。PHP有一个非常简单的垃圾回收器,用于回收不在作用域内的对象。它的原理是通过引用计数,当计数到达0时(意味着不再有引用指向该对象),该对象被回收,释放占用的内存。
这种方式简单高效,但是在父子关系的对象引用中会产生问题。此时,这些对象的引用计数器不为0,所以不会被回收,一直存在到请求的结束。下面我们来看这个问题的一个例子。
Listing11.Parent-childclassrelationshipnotproperlygarbagecollectedinPHPV5.2andearlier
PHP代码
classParent
{
publicfunction__construct()
{
$this->child=newChild($this);
}
}
classChild
{
publicfunction__construct(
Parent$parent
)
{
$this->parent=$parent;
}
}
for($i=0;$i<1000;$i++){
newParent();
}
在这个例子中,你每次创建一个Parent对象,然后该对象不再被引用,但是内存不会被释放,所以脚本的内存消耗持续增加。在用户空间,存在一些方法来解决该问题,比如为Parent类提供一个析构函数,直接释放引用的子对象。但是你必须在释放Parent对象前显式调用该析构函数,如果一直这么做,将使你的代码变得非常复杂。
在PHPV5.3中,垃圾回收器将会检测这种循环引用并释放它们,从而使该脚本的内存使用保持在正常状态。当Parent对象的引用计数为0时,Parent内部引用的Child对象也将被回收。
总结
PHP在支持面向对象编程方面走过了漫漫长路,从PHPV4时的弱支持到PHPV5中的飞跃以及后续版本的改进。现在PHPV5.3又加入了一些令人兴奋的改进,包括语法上的改进,如新的
原文链接:http://www.ibm.com/developerworks/opensource/library/os-php-5.3new1/index.html
2004年PHPV5发布,和PHPV4相比,它在面向对象编程(OOP)和设计方面有了巨大的进步,增加了一些必要的特性,如类的可见性、正确的构造函数与析构函数、类型提示和类反射API。PHP5为高级面向对象编程开启了方便之门,使得开发者可以更简单地实现各种设计模式,设计出更好的类和API。
在PHPV5.3中,继续大幅加强OOP能力,这些改进包括语法的进化和性能的改善等方面。首先让我们来看静态方法和属性相关的新特性。
改进后的静态方法与属性的处理方式
PHPV5中一个实用的新增特性是可以指定类的一个方法或属性为静态成员(PHPV4支持静态地访问类的方法和属性,但是无法指定它们是为静态访问而设计的)。静态访问在实现单例模式时非常有用,此时,类只存在一个实例。
PHPV5.3增加了若干特性,以加强对类的静态方法和属性的支持。首先,我们来分析新增的魔术方法:
__callStatic()。
__
callStatic()魔术方法
PHPV5包含了若干个可以用于类内部的魔术方法。如果在类中定义了这些方法,它们可以提供特殊的功能,从而实现重载(允许一个方法接收不同类型的参数)和多态(允许不同数据类型使用相同的接口)功能。同时,它们也让PHP中的面向对象编程(OOP)和设计模式的实现变得更加简单。
在PHPV5.3中,新增了一个魔术方法:
__callStatic()。它和
__call()魔术方法类似,后者用于处理类中不存在或不可见的方法调用。而
__callStatic()用于处理类似的静态方法调用,方便开发者实现方法的重载。下面是一个如何使用的例子。
Listing1.Exampleofusing
__callStatic()vs.
__call()
PHP代码
classFoo
{
publicstaticfunction__callStatic(
$name,
$args
)
{
echo"Calledmethod$namestatically";
}
publicfunction__call(
$name,
$args
)
{
echo"Calledmethod$name";
}
}
Foo::dog();//输出"Calledmethoddogstatically"
$foo=newFoo;
$foo->dog();//输出"Calledmethoddog"
需要注意,PHP要求
__callStatic()方法必须是public,而且是static。类似的,
__call()魔术方法也要求定义为public,其实所有的魔术方法都要求定义为public。
动态的静态调用
PHP中有一个实用的特性是变量的变量。它意味着你可以用一个变量的字符串值作为另外一个变量的名字。换句话说,你可以完成下面的功能。
Listing2.Variablevariables
PHP代码
x='y';
$$x='z';
echo$x;//输出'y'
echo$$x;//输出'z'
同样的概念可以用于函数,甚至类的成员函数,如下例所示。
Listing3.Variablefunctionandclassmethodnames
PHP代码
classDog
{
publicfunctionbark()
{
echo"Woof!";
}
}
$class='Dog'
$action='bark';
$x=new$class();//实例化类'Dog'
$x->$action();//输出"Woof!"
在PHPV5.3中增加了一个功能,静态调用中的类名可以通过一个变量来指定。由此引入了一些新的编程方法,如下所示。
Listing4.Variableclassnaming
PHP代码
classDog
{
publicstaticfunctionbark()
{
echo"Woof!";
}
}
$class='Dog';
$action='bark';
$class::$action();//输出"Woof!"
这个新增功能使得PHP中变量的变量这个特性成为一个完备特性,可用于各种环境。
接下来让我们关注另外一个更加实用的关于静态方法和属性方面的功能改善:静态调用的晚绑定。
静态调用的晚绑定(膘叔:是否叫后绑定或者延迟绑定较好?)
PHPV5.3之前一个令人恼火的事情是静态方法和属性的处理。到目前为止,静态引用,包括使用self或__CLASS__,都是在函数定义所在类的范围内解析。当继承一个类,并在子类中调用静态函数时,将会发生解析错误。PHPV5.3中新增的静态调用晚绑定特性解决了这个问题。为了更好的说明这个问题,我们创建如下一个包含静态方法的类。
Listing5.Class
Foowithstaticmethod
test()
classFoo
{
protectedstatic$name='Foo';
publicstaticfunctiontest()
{
returnself::$name;
}
}
然后继承这个类,并在子类中重定义$name属性。
Listing6.Childclass
Barthatextendsparentclass
Foo
PHP代码
classBarextendsFoo
{
protectedstatic$name='Bar';
}
最后进行一个静态调用。
Listing7.Staticmethodcall
test()
这个调用的输出将是字符串
Foo。因为test()方法中的
self::$name引用是在
Foo这个类中解析。而PHP解释器这么做是因为test()方法是在类Foo中定义的。
PHPV5.3通过使用static关键字,使得该引用可以在当前类中解析。将上面的类Foo改写为如下定义(译注:注意红色部分),输出将变为Bar。
Listing8.Usingthestatickeyword
PHP代码
classFoo
{
protectedstatic$name='Foo';
publicstaticfunctiontest()
{
returnstatic::$name;
}
}
classBarextendsFoo
{
protectedstatic$name='Bar';
}
echoBar::test();//输出'Bar'
需要注意的是,static关键字的这种用法在非静态上下文中无效。也就是说普通的继承规则对静态调用无效。static关键字将简单的去尝试在当前类中进行解析,而不是函数定义所在的类。这是一个需要我们注意的事情。
在分析了一些有关静态方法和属性方面的改善之后,我们来看看PHPV5中非常重要的部分:标准PHP库中新增的一些类。
标准PHP库
PHPV5中新增的标准PHP库是用于解决标准问题的一组类和接口。这些问题包括可迭代对象、数组对象和链表等。使用这些类和接口的好处是:它们是PHP的原生方法,比用PHP实现的效率要高。同时,它们使得许多PHP内置函数和语言结构可以直接使用这些对象,比如你可以通过foreach结构遍历一个实现了迭代器接口的对象。
PHPV5.3在SPL中增加了若干个类。如早前提到过的双向链表SplDoublyLinkedList。SPL中新增的栈和队列类:SplStack和SplQueue的实现中都使用了该类。
下面看一下如何使用
SplStack类实现一个栈。
Listing9.Using
SplStack
PHP代码
$stack=newSplStack();
//pushafewnewitemsonthestack
$stack->push('a');
$stack->push('b');
$stack->push('c');
//seehowmanyitemsareonthestack
echocount($stack);//returns3
//iterateovertheitemsinthestack
foreach($stackas$item)
echo"[$item],";
//theaboveoutputs:[c],,[a]
//popanitemoffthestack
echo$stack->pop();//returns'c'
//nowseehowmanyitemsareonthestack
echocount($stack);//returns2
SplQueue类与SplStack相似,实现了队列功能(先进先出,而栈是先进后出)。此外,还实现了堆(SplHeap)以及一些特殊的队列和堆实现,如(
SplMinHeap、
SplMaxHeap和
SplPriorityQueue)。
另外新增的一个实用类是
SplFixedArray,如名字暗示的那样,它是一个固定大小的数组实现。不过,它的速度比PHP内置的数组要快20-30%,原因是它是固定大小的,而内置数组是变长的,并且它只允许数字索引。下面演示了它的用法。
[b]Listing10.
SplFixedArray
PHP代码
$array=newSplFixedArray(3);
$array[0]='dog';
$array[1]='cat';
$array[2]='bird';
$a->setSize(4);//increasethesizeonthefly
$array[3]='mouse';
foreach($arrayas$value)
echo"[$value],";
Output:
[dog],[cat],[bird],[mouse]
此外,还增加了两个迭代器类:
FilesystemIterator和
GlobIterator。它们的行为与PHP中的其它迭代器一致,只不过它们是为特定目的而定制的。
另外一个变化是SPL在PHPV5.3中将强制启用。以前的PHPV5版本,你可以在编译的时候禁止SPL,但是这个选项现在没有了。
SPL的改善提高了PHP的易用性,并实现了数据结构如双向链表、栈、堆和队列等。它们可以替换用户自己实现的这些数据结构,这样不但可以提高效率,而且还可以促进PHP函数和语言结构的整合。
讨论完SPL的改进之后,我们看看PHPV5.3如何通过采用循环垃圾回收技术来提高OOP的性能与内存消耗。
循环垃圾回收
PHP开发者经常碰到的一个性能瓶颈是垃圾回收。PHP有一个非常简单的垃圾回收器,用于回收不在作用域内的对象。它的原理是通过引用计数,当计数到达0时(意味着不再有引用指向该对象),该对象被回收,释放占用的内存。
这种方式简单高效,但是在父子关系的对象引用中会产生问题。此时,这些对象的引用计数器不为0,所以不会被回收,一直存在到请求的结束。下面我们来看这个问题的一个例子。
Listing11.Parent-childclassrelationshipnotproperlygarbagecollectedinPHPV5.2andearlier
PHP代码
classParent
{
publicfunction__construct()
{
$this->child=newChild($this);
}
}
classChild
{
publicfunction__construct(
Parent$parent
)
{
$this->parent=$parent;
}
}
for($i=0;$i<1000;$i++){
newParent();
}
在这个例子中,你每次创建一个Parent对象,然后该对象不再被引用,但是内存不会被释放,所以脚本的内存消耗持续增加。在用户空间,存在一些方法来解决该问题,比如为Parent类提供一个析构函数,直接释放引用的子对象。但是你必须在释放Parent对象前显式调用该析构函数,如果一直这么做,将使你的代码变得非常复杂。
在PHPV5.3中,垃圾回收器将会检测这种循环引用并释放它们,从而使该脚本的内存使用保持在正常状态。当Parent对象的引用计数为0时,Parent内部引用的Child对象也将被回收。
总结
PHP在支持面向对象编程方面走过了漫漫长路,从PHPV4时的弱支持到PHPV5中的飞跃以及后续版本的改进。现在PHPV5.3又加入了一些令人兴奋的改进,包括语法上的改进,如新的
__callStatic()魔术方法、动态的静态调用、静态调用的晚绑定和静态方法和属性的支持。SPL上则增加了双向链表、栈、堆和队列的实现,为开发者提供了现成的常用数据结构并提高它们的易用性。最后,期盼已久的循环垃圾回收器修复了自引用类导致的内存和性能问题,通过这个大幅改进的垃圾回收器,正确释放循环引用的对象。上述PHPV5.3成为一个更强大的面向对象编程语言。
的特性,让
原文链接:
相关文章推荐
- PHP V5.3 中的新特性,第 1 部分: 对象接口的变化
- php中的类与对象(抽象、接口与特性)
- PHP V5.3 中的新特性,第 1 部分:对象接口的变化
- php5.3,5.4,5.5,5.6 中新特性
- PHP的ArrayAccess接口 像数组一样来访问你的PHP对象
- C++和PHP在面性对象特性上的对比
- PHP 5.3中的新特性
- PHP对象接口
- PHP 5.3中的新特性
- PHP对象高级特性
- PHP 5.3 5.4 5.5新特性(二)
- PHP5.3新特性之语言特性
- php5.3 新特性
- php学习笔记--3. 抽象类 与 对象接口
- PHP面向对象程序设计高级特性详解(接口,继承,抽象类,析构,克隆等)
- PHP5.3的新特性介绍,转自:http://www.quou.cn/
- php5.3的新特性总结
- php学习笔记 面向对象中[接口]与[多态性]的应用
- php 对象的一些特性
- PHP入门教程之面向对象的特性分析(继承,多态,接口,抽象类,抽象方法等)