php5.4新功能Traits介绍

1. traits

Traits是在5.4中新增的一个用于实现代码重用的方法。

php是一种单一继承的语言,我们无法像java一样在一个class中extends多个基类来实现代码重用,现在Traits能解决这一代码重用的问题,它能让开发者在多个不同的class中实现代码重用。

Traits和class在语义的定义上都是为了减少代码的复杂性,避免多重继承的问题。

Traits 和class相似,但是仅用于以统一和较细粒度的方式来提供一组功能,在Traits内部无法进行实例化,即不存在类似class的构造函数__construct()。Traits作为一个php传统继承的扩展并实现水平集成;因此,在应用程序的class中可以不再需要继承。

1)如何使用

在类中用关键字'use' 来引用 Traits。多个Traits 用','隔开。

实例代码如下:

  1. <?php
  2. trait ezcReflectionReturnInfo {
  3. function getReturnType() {
  4. }
  5. function getReturnDescription() {
  6. }
  7. }class ezcReflectionMethod extends ReflectionMethod {
  8. use ezcReflectionReturnInfo;
  9. /* ... */
  10. }
  11. class ezcReflectionFunction extends ReflectionFunction {
  12. use ezcReflectionReturnInfo;
  13. /* ... */
  14. }
  15. ?>

2)优先级

基类中的成员函数将被Traits中的函数覆盖,当前类中的成员函数将覆盖Traits中的函数。

  1. <?php
  2. class Base {
  3. public function sayHello() {
  4. echo 'Hello ';
  5. }
  6. }
  7. trait SayWorld {
  8. public function sayHello() {
  9. parent::sayHello();
  10. echo "World!\n";
  11. }
  12. }
  13. class MyHelloWorld extends Base {
  14. use SayWorld;
  15. }
  16. class MyHelloWorldExt extends Base {
  17. use SayWorld;
  18. public function sayHello() {
  19. /**
  20. * 这里是5.4中的新的改动,5.4之前的版本会提示:
  21. * PHP Fatal error:  Cannot use string offset as an array
  22. * 5.4中改进为返回字符串中的该索引号的字符
  23. */
  24. $str  = "Arvin";
  25. echo $str[0][0];// echo 'A';
  26. }
  27. public function shortArray() {
  28. $array = ['first', 2, 3, 4];//5.4中的数组简单语法
  29. echo $array[0];//5.4中的数组解引用取数组元素方法
  30. }
  31. }
  32. $o = new MyHelloWorld();
  33. $o->sayHello();
  34. $oe = new MyHelloWorldExt();
  35. $oe->sayHello();
  36. echo "\n";
  37. $oe->shortArray();
  1. 输出:
  2. Hello World!
  3. A
  4. first

3)多Traits

多个Traits可以添加到一个class的声明中,多个Traits之间用","隔开。

  1. <?php
  2. trait Hello {
  3. public function sayHello() {
  4. echo 'Hello ';
  5. }
  6. }
  7. trait World {
  8. public function sayWorld() {
  9. echo 'World';
  10. }
  11. }
  12. class MyHelloWorld {
  13. use Hello, World;
  14. }
  15. $o = new MyHelloWorld();
  16. $o->sayHello();
  17. $o->sayWorld();
  18. ?>

输出结果:

Hello World

4)多Traits冲突

如果添加到同一个class的两个Traits中有相同的函数名称,且没有明确的进行处理,将产生一个错误。

为了解决同一个类中两个Tratis中的同名函数冲突,需要用insteadof操作符来选择正确的函数。

因为方法的唯一性和排他性,'as'操作符允许用在冲突函数之后以解决内部冲突的问题。

  1. <?php
  2. trait A {
  3. public function smallTalk() {
  4. echo 'a';
  5. }
  6. public function bigTalk() {
  7. echo 'A';
  8. }
  9. }
  10. trait B {
  11. public function smallTalk() {
  12. echo 'b';
  13. }
  14. public function bigTalk() {
  15. echo 'B';
  16. }
  17. }
  18. class Talker {
  19. use A, B {
  20. B::smallTalk insteadof A;
  21. A::bigTalk insteadof B;
  22. }
  23. }
  24. class Aliased_Talker {
  25. use A, B {
  26. B::smallTalk insteadof A;
  27. A::bigTalk insteadof B;
  28. B::bigTalk as talk;
  29. }
  30. }
  31. ?>

上面的例子中,Talker使用Traits A 和B,因此两者中相同的函数名称存在冲突。

alker中定义了smallTalk取自Traits B,bigTalk取自Traits A。

Aliased_Talker中通过使用as操作符来确保Traits B中的bigTalk通过别名talk来实现。

5)改变函数访问权限

我们可以使用as语法来改变Traits中函数的访问权限属性。

  1. <?php
  2. trait HelloWorld {
  3. public function sayHello() {
  4. echo 'Hello World!';
  5. }
  6. }
  7. // Change visibility of sayHello,改变sayHello的访问权限。
  8. class MyClass1 {
  9. use HelloWorld { sayHello as protected; }
  10. }
  11. // Alias method with changed visibility
  12. // sayHello visibility not changed,设置别名myPrivateHello。
  13. class MyClass2 {
  14. use HelloWorld { sayHello as private myPrivateHello; }
  15. }
  16. ?>

6)Traits组成新Traits

就像许多类一样可以在类中使用Traits,Traits中一样可以使用Traits。可以在一个Traits中定义一个或者多个Traits,这些Traits 可以作为部分或者全部成员被定义在其他Traits中。

  1. <?php
  2. trait Hello {
  3. public function sayHello() {
  4. echo 'Hello ';
  5. }
  6. }
  7. trait World {
  8. public function sayWorld() {
  9. echo 'World!';
  10. }
  11. }
  12. trait HelloWorld {
  13. use Hello, World;
  14. }
  15. class MyHelloWorld {
  16. use HelloWorld;
  17. }
  18. $o = new MyHelloWorld();
  19. $o->sayHello();
  20. $o->sayWorld();
  21. ?>

以上例程会输出:

  1. Hello World!

7)抽象Trait成员

为了在类中强制实现某些方法,可以在Traits中使用抽象方法。

例如:

  1. <?php
  2. trait Hello {
  3. public function sayHelloWorld() {
  4. echo 'Hello '.$this->getWorld();
  5. }
  6. abstract public function getWorld();
  7. }
  8. class MyHelloWorld {
  9. private $world;
  10. use Hello;
  11. public function __construct($world) {
  12. $this->world = $world;
  13. }
  14. public function getWorld() {
  15. return $this->world;
  16. }
  17. }
  18. /**
  19. * 这里用到了5.4新功能 类实例化解引用操作
  20. * (new class())->method();
  21. */
  22. (new MyHelloWorld('Arvin'))->sayHelloWorld();
  23. ?>
  24. 该实例输出:
  25. Hello Arvin

8)静态Trait成员

在Traits中不能定义static 静态变量,但是可以定义在Tratis的函数中。Tratis中同样可以定义静态函数。

  1. <?php
  2. trait Counter {
  3. public function inc() {
  4. static $c = 0;//静态变量
  5. $c += 1;
  6. echo "$c\n";
  7. }
  8. /**
  9. * 静态方法
  10. */
  11. public static function doSomething() {
  12. echo 'Doing something';
  13. }
  14. }
  15. class C1 {
  16. use Counter;
  17. }
  18. (new C1())->inc(); // echo 1
  19. C1::doSomething();
  20. ?>
  21. 输出为:
  22. 1
  23. Doing something

9) Traits 定义属性

如果在一个trait中定义了一个属性,则在引用该trait的类中不能定义同名的属性,如果该类中定义有和trait中已定义属性具有相同的名字和访问可见性,则是一个E_STRICT 提示,否则抛出语法错误。

<?php
trait PropertiesTrait {
public $x = 1;
public $y = 2;
} class PropertiesExample {
use PropertiesTrait;
public $x = 1;
//public $y = 3;
} $example = new PropertiesExample;
echo $example->x, $example->y;
?> 输出:
12

在最后贴上php5.4.0部分新功能changelog:

Added short array syntax support ([1,2,3]), see UPGRADING guide for full details.
Added binary numbers format (0b001010).
Added support for Class::{expr}() syntax.
Added support for Traits.//本文的主要内容
Added closure $this support back.
Added array dereferencing support.//数组解引用支持,上文中有实例
Added callable typehint.
Added indirect method call through array. #47160.
Added DTrace support.//传说DTrace是一个性能分析工具,可以跟踪出函数调用点,返回点等数据
Added class member access on instantiation (e.g. (new foo)->bar()) support.//类新实例解引用操作,上文中有实例
转载  http://blog.csdn.net/longlongmylove/article/details/7521379

php5.4新功能Traits的更多相关文章

  1. PHP5各个版本的新功能和新特性总结

    因为 PHP 那“集百家之长”的蛋疼语法,加上社区氛围不好,很多人对新版本,新特征并无兴趣.本文将会介绍自 PHP5.2 起,直至 PHP5.6 中增加的新特征 本文目录:PHP5.2 以前:auto ...

  2. PHP5各个版本的新功能和新特性总结(转载 http://www.jb51.net/article/48150.htm)

    本文目录:PHP5.2 以前:autoload, PDO 和 MySQLi, 类型约束PHP5.2:JSON 支持PHP5.3:弃用的功能,匿名函数,新增魔术方法,命名空间,后期静态绑定,Heredo ...

  3. PHP 5.2、5.3、5.4、5.5、5.6 版本区别对比以及新功能详解

    截至目前(2015.1), PHP 的最新稳定版本是 PHP5.5, 但有差不多一半的用户仍在使用已经不在维护  的 PHP5.2, 其余的一半用户在使用 PHP5.3 . 因为 PHP 那“集百家之 ...

  4. 从淘宝 UWP 的新功能 -- 比较页面来谈谈 UWP 的窗口多开功能

    前言 之前在 剁手党也有春天 -- 淘宝 UWP ”比较“功能诞生记 这篇随笔中介绍了一下 UWP 淘宝的“比较”新功能呱呱坠地的过程.在鲜活的文字背后,其实都是程序员不眠不休的血泪史(有血有泪有史) ...

  5. Sql Server 2016新功能之 Row-Level Security

    Sql Server 2016 有一个新功能叫 Row-Level Security ,大概意思是行版本的安全策略(原来我是个英语渣_(:з」∠)_) 直接上例子.这个功能相当通过对表添加一个函数作为 ...

  6. What's new in Windows 10 Enterprise with Microsoft Edge.(Windows 10 新功能)

    What's new in Windows 10 Enterprise with Microsoft Edge --带有Edge浏览器的Windows 10 企业版的新功能 本文摘录自公司群发邮件, ...

  7. MySQL 5.7 Replication 相关新功能说明

    背景: MySQL5.7在主从复制上面相对之前版本多了一些新特性,包括多源复制.基于组提交的并行复制.在线修改Replication Filter.GTID增强.半同步复制增强等.因为都是和复制相关, ...

  8. SQL Server2016 新功能实时查询统计信息

    SQL Server2016 新功能实时查询统计信息 很多时候有这样的场景,开发抱怨DBA没有调优好数据库,DBA抱怨开发写的程序代码差,因此,DBA和开发都成为了死对头,无法真正排查问题. DBA只 ...

  9. 一个新人如何学习在大型系统中添加新功能和Debug

    文章背景: 今年七月份正式入职,公司主营ERP软件,楼主所在的组主要负责二次开发,使用的语言是Java. 什么叫二次开发呢?ERP软件的客户都是企业.而这些企业之间的情况都有所不同,一套标准版本的企业 ...

随机推荐

  1. 【Jquery系列】之Jquery 选择器

    1   概述 本篇文章为穿插文章,ASP.NET MVC系列目前写了如下几篇: 详解google Chrome浏览器(理论篇) 详解Google Chrome浏览器(操作篇)(上) 详解Google ...

  2. 【golang-GUI开发】Qt5的安装

    golang一直被认为没有好的GUI库,事实并非如此. 目前有基于gtk+3.0的gotk3:https://github.com/gotk3/gotk3 以及接下来我们要说的qt:https://g ...

  3. Redis学习笔记(2)-新建虚拟电脑,安装系统CentOSMini

    下载CentOSMini download 点击download,网页显示结果如下 点击红框,跳转至镜像页面,选择任一镜像,下载即可. 新建虚拟机,装载CentOSMini 点击新建 输入名称 输入C ...

  4. .NET里面 abstract class和Interface有什么区别以及用法的展现?

    前言 很多新人对这个问题已经看到的厌倦或者是恶心了,有可能是因为比较难理解或者是未理解的情况下对它们的认知不够所以产生的想法是差不多,不用抽奖类和接口我一样能实现我想要的功能. 这句话确实不假,但是实 ...

  5. petapoco 实体中字段去掉关联(类似于EF中的NotMap)

    怎么才能让不是数据库表中的字段放在实体中而不影响正常的插入和更新呢? 找到 PetaPoco.cs 文件,打开之后,搜索插入方法(Insert),然后继续找到下一层方法 就能看到如下代码: 看到这个注 ...

  6. 设计模式—模板方法的C++实现

    这是Bwar在2009年写的设计模式C++实现,代码均可编译可运行,一直存在自己的电脑里,曾经在团队技术分享中分享过,现搬到线上来. 1. 模板方法简述 1.1 目的 定义一个操作中的算法骨架,而将一 ...

  7. Java基础-一文搞懂位运算

    在日常的Java开发中,位运算使用的不多,使用的更多的是算数运算(+.-.*./.%).关系运算(<.>.<=.>=.==.!=)和逻辑运算(&&.||.!), ...

  8. JavaScript是如何工作: 深入探索WebSocket和HTTP/2与SSE + 如何选择正确的路径!

    原文:<JavaScript是如何工作: 深入探索 websocket 和HTTP/2与SSE +如何选择正确的路径! 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 文章底部分 ...

  9. crontab 配置文件

    1.系统配置文件 etc/crontab 2.vim打开crontab 以上配置解释 1. 代表用bash去执行shell command line2.代表crontab 默认的环境变量3.cront ...

  10. 前端入门8-JavaScript语法之数据类型和变量

    声明 本系列文章内容全部梳理自以下几个来源: <JavaScript权威指南> MDN web docs Github:smyhvae/web Github:goddyZhao/Trans ...