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

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

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

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

1)如何使用

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

实例代码如下:

<?php
trait ezcReflectionReturnInfo {
function getReturnType() {
}
function getReturnDescription() {
}
}class ezcReflectionMethod extends ReflectionMethod {
use ezcReflectionReturnInfo;
/* ... */
}
class ezcReflectionFunction extends ReflectionFunction {
use ezcReflectionReturnInfo;
/* ... */
}
?>

2)优先级
基类中的成员函数将被Traits中的函数覆盖,当前类中的成员函数将覆盖Traits中的函数。

<?php
class Base {public function sayHello() {echo 'Hello ';}
}trait SayWorld {public function sayHello() {parent::sayHello();echo "World!\n";}
}class MyHelloWorld extends Base {use SayWorld;
}class MyHelloWorldExt extends Base {use SayWorld;public function sayHello() {/*** 这里是5.4中的新的改动,5.4之前的版本会提示:* PHP Fatal error:  Cannot use string offset as an array* 5.4中改进为返回字符串中的该索引号的字符*/$str  = "Arvin";echo $str[0][0];// echo 'A';}public function shortArray() {$array = ['first', 2, 3, 4];//5.4中的数组简单语法echo $array[0];//5.4中的数组解引用取数组元素方法}
}$o = new MyHelloWorld();
$o->sayHello();
$oe = new MyHelloWorldExt();
$oe->sayHello();
echo "\n";
$oe->shortArray();
输出:
Hello World!
A
first

3)多Traits

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

<?php
trait Hello {public function sayHello() {echo 'Hello ';}
}trait World {public function sayWorld() {echo 'World';}
}class MyHelloWorld {use Hello, World;
}$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();

输出结果:

Hello World

4)多Traits冲突

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

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

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

<?php
trait A {
public function smallTalk() {
echo 'a';
}
public function bigTalk() {
echo 'A';
}
}trait B {
public function smallTalk() {
echo 'b';
}
public function bigTalk() {
echo 'B';
}
}class Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
}
}class Aliased_Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
B::bigTalk as talk;
}
}

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

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

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

5)改变函数访问权限

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

<?php
trait HelloWorld {
public function sayHello() {
echo 'Hello World!';
}
}// Change visibility of sayHello,改变sayHello的访问权限。
class MyClass1 {
use HelloWorld { sayHello as protected; }
}// Alias method with changed visibility
// sayHello visibility not changed,设置别名myPrivateHello。
class MyClass2 {
use HelloWorld { sayHello as private myPrivateHello; }
}

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

<?php
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}trait World {
public function sayWorld() {
echo 'World!';
}
}trait HelloWorld {
use Hello, World;
}class MyHelloWorld {
use HelloWorld;
}$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();

以上例程会输出:Hello World!

7)抽象Trait成员
为了在类中强制实现某些方法,可以在Traits中使用抽象方法。
例如:

<?php
trait Hello {public function sayHelloWorld() {echo 'Hello '.$this->getWorld();}abstract public function getWorld();
}class MyHelloWorld {private $world;use Hello;public function __construct($world) {$this->world = $world;}public function getWorld() {return $this->world;}
}/*** 这里用到了5.4新功能 类实例化解引用操作* (new class())->method();*/
(new MyHelloWorld('Arvin'))->sayHelloWorld();
?>该实例输出:
Hello Arvin

8)静态Trait成员

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

<?php
trait Counter {public function inc() {static $c = 0;//静态变量$c += 1;echo "$c\n";}/*** 静态方法*/public static function doSomething() {echo 'Doing something';}
}class C1 {use Counter;
}(new C1())->inc(); // echo 1
C1::doSomething();
?>
输出为:
1
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

traits的作用和使用相关推荐

  1. 2021-11-19迭代器的设计原则和iterator Traits的作用与设计

    iterator Traits 的作用是提取出 iteration 的五个性质: 1)iterator_category 迭代器的种类,是否可以间隔跳跃,是单向前进还是两端都可以. 2)value_t ...

  2. 迭代器的设计原则和Iterator Traits的作用与设计

    一.迭代器设计原则 迭代器是容器与算法处理的桥梁 category分类,类别 difference_type两个迭代器之间的距离的类型,容器最大能放多少元素,超过differene_type会有问题. ...

  3. 《STL源码剖析》学习--traits

    在本书迭代器一节提到了Traits编程技法,将其誉为stl源码门匙,在<C++编程思想>一书中,将其列为模板编程中的习语"特征",这里进行总结. traits技术 也往 ...

  4. 第三章 迭代器(iterators)概念与traits编程技法

    迭代器(iterators)概念与traits编程技法 3.1 迭代器设计思想--STL关键所在 3.2 迭代器(iterators)是一种smart pointe 3.3 迭代器相应型别(assoc ...

  5. traits简单介绍

    traits class是个类模板,在不修改一个实体(通常是数据类型或常量)的前提下,把属性和方法关联到一个编译时的实体.在c++中的具体实现方式是:首先定义一个类模板,然后进行显式特化或进行相关类型 ...

  6. C++ Traits编程技法--从迭代器的设计看参数推导与类型推导

    代码上传至 https://github.com/gatieme/AderXCoding/tree/master/language/cpp/iterator_associate_type 或者 htt ...

  7. STL萃取(Traits)机制

    问题前述 我们希望有一个类,并有一个成员方法 GetSum 可以完成数组元素的一系列运算.具体看如下代码: #include <iostream> using namespace std; ...

  8. boost源码剖析之:泛型编程精灵type_traits(rev#2)

    boost源码剖析之:泛型编程精灵type_traits(rev#2) 刘未鹏 C++的罗浮宫(http://blog.csdn.net/pongba) 动机 使用traits的动机一般有三种,分派. ...

  9. 【侯捷】C++STL标准库与泛型编程(第二讲)

    第二讲 应具备的基础 C++基本语法 模板(Template)基础 令你事半功倍 数据结构(Data Structures)和算法(Algorithms)概念 令你如鱼得水 书籍: <Algor ...

最新文章

  1. redmine 2.2.x 修改文档附件的存放目录
  2. 面试官,别再问高并发了!
  3. 牛客练习赛26 D xor序列 (线性基)
  4. jQuery源码解析(2)—— Callback、Deferred异步编程
  5. ROS 教程之 network:多台计算机之间网络通信(2)
  6. Python3常用正则表达式
  7. Asp.net服务器端控件替换客户端控件
  8. 当软件定义汽车成为趋势,未来汽车是否可以理解为四个轮子上的超级计算机?
  9. Hadoop原理之——HDFS原理
  10. WOWZA的安装及(VOD+LIVE)简单配置和VLC RTP推流
  11. 《前端》阿里字体库iconfont使用方法
  12. pytorch创建新环境
  13. 电脑bios进入方法介绍
  14. 问什么说我的计算机主机名无效,为什么arcgis的许可管理器 修改为主机时,总是说我输入的是无效主机名...
  15. Retrofit2+Rxjava2+okHttp 网络框架封装
  16. 【vue3 Api - watchEffect 的讲解 使用】- 侦听响应式数据执行副作用(effect)函数
  17. Asp.net Core 入门实战
  18. Virgo与Maven整合开发环境搭建(二)
  19. 从Java字符串中移除Emojis字符的多种方法
  20. week10 字幕提取

热门文章

  1. [附源码]Java计算机毕业设计SSM电影票购票系统
  2. MySQL使用kill杀不死
  3. 6-5 使用函数求余弦函数的近似值 (15分)
  4. 为什么使用 MD5 存储密码非常危险
  5. ingress使用80和443对外提供服务
  6. 初、中、高级测试工程师面试题汇总(附答案)
  7. 自动化测试方面的基础知识
  8. 2020-04-01
  9. dsl java 语言_5种语言下的DSL实现
  10. Emmet 插件使用教程