本文参考:  http://php.net/language.oop5.traits

一、什么是trait

从PHP 5.4.0 开始 PHP 实现了一种新的代码复用方式 trait。

二、trait解决了什么问题

trait 的出现是为了解决类似PHP的单继承语言而准备的一种代码复用机制,让开发人员能够在不能层次结构内独立的类中复用 method。

三、跟其它语言相比,trait 有什么 好处

Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。

四、该如何使用trait

  • 示例1,如何使用 trait

    <?php
    trait ezcReflectionReturnInfo {
    function getReturnType() { /*1*/ }
    function getReturnDescription() { /*2*/ }
    } class ezcReflectionMethod extends ReflectionMethod {
    use ezcReflectionReturnInfo;
    /* ... */
    } class ezcReflectionFunction extends ReflectionFunction {
    use ezcReflectionReturnInfo;
    /* ... */
    }
    ?>
  • 示例2 ,trait 与 class 方法优先级问题
    trait 方法会覆盖基类中的方法,当前类中的方法会覆盖 trait 方法
    <?php
    class Base {
    public function sayHello() {
    echo 'Hello ';
    }
    } trait SayWorld {
    public function sayHello() {
    parent::sayHello();
    echo "World!\r\n";
    }
    } class MyHelloWorld extends Base {
    use SayWorld;
    } class MyNewHelloWorld extends Base{
    use SayWorld;
    public function sayHello(){
    echo "Hello sunshine!\r\n";
    }
    } $o = new MyHelloWorld();
    $o->sayHello(); $b = new MyNewHelloWorld();
    $b->sayHello();
    ?>

    上面的代码会输出:

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUQAAAAuCAIAAADfkPcZAAAETklEQVR4nO2d25WsIBBFzcdUTKTXMhGymB/zMLT58AXUg5fYTs3Zf/eCBQi7UZpmhp+fn8/nMzBMbl2XeeSSTsZ5WdfVTWKGya00yuToRUzGLXjAcRGTRPJMTkkUggQV2AL4V0wzuR9KJdvvQ5Rhb1F4BdtML0+yi5JNoCVo0VoZ54UZd2yHp0anR+ouZfaFFqGkfXo1lFL09BfLzNTdu8i7KdtlR14+j1BNv4BUutRSpZKN94FkOBoURYpqEKSmZY4up30e3MYCg6rgZabVLNPouJNXDO4W5vSFGKGwMnJTtN7Uk9tkBuBmZJmv9PL5kHP16Qj90WVOT0sANEMePW+fRCAzZAaPAJnvQZYZADNA5lqSc7qNSb+mFRnLUQBUApmruVPm1LIPAGk6P2YnZyIbU1V2KyAz6AeRmXk3aBDuOzJPTgypJDUAmcELMCuzYMbkejgDmcELqJbZf2OUR2GLzOn9W2pQMWbuFjGvaqmNYlozgy1DkBn0o0rm1K5m5dLcDMmd1Sr+1Ew25eVu3t6rNkeNLZFZ2EMOmUEPKmTeR2i8+1uZXYtl3j27RvdeZu5w96bmINQ4L0eMdBGXief/SW/cQjO3Mq6IzPZxPwBkBk3wMmvTCTPu5KFYJzP36bBlzB3v59R8Gnk+LvuOq0WQDy0Z5SOJ+yUYZAY9KJc5mcGnQeZ4aBctlZ1T8OTWZZ72f8UTs15EQYFsVu4/xZh9VtnBv6L8MftPyHzIsS947RO1ZwxkBuaolLno5fULj9m7vtO+eL29Q8/XxJz/mP2QzAA0U7EAxh54MYzzfNvM3LwAdujrnL/y5dxCWpFcAKuXmbx0h+/vANxM1VdT+UeofOmrqYHIStzN/mqqXmbmp33OaRmxAgZauGXTiDwOv7NpxLs6monZJ2GhiHaZwxKOJTjIDPqA3zMDYATIDIARIDMARoDMABgBJ4104y+cGgUsAZm7USIz/939rWD7t3lwbFA3IDN4FpMnjbyDlz1mQ2bzQOZuQGbwLCaPDeIjBPWkzYx+QHJlUM8MyipCihCvHch/WU4/tyirLyCzeWweGyRUknU1KDHOEJ8ZFDY0pwgtQp7MxXXg+wIym8fmsUFS4HEsk5lz77oopwg9glh6boSCvoDM5jF6bNDAfCDQ1LTMYR1i4zKKSETQE5IRSvoCMpvH6LFBtKbJP64tvjNr9SorokpmLUJRX+AwE+tYPTYojhbX8SaZy4qAzKAnVo8NooRBSSvi+EUqykU8IDMencGG1WODhsllPF+Qp40imXOK6CtzUV8A61g/NkiKQL8fnosfsxNFPCFzfl/gMBP7mD02KF3FK/k4YbtxAYxL6y5zRkOHYYDM/wH8nhkAI0BmAIwAmQEwAmQGwAiyzGSZVNw1gp0IneAWwCxC/1iAskw3zgtW8Xj6ysx/Dfoq/NYwgyQYZ9WDqPI+PCZz2KVMif5tuL9CuTK3/yjWNL/kSiZTDjjUPwAAAABJRU5ErkJggg==" alt="" />

  • 示例3  同时使用多个 trait  通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中。
    <?php
    trait Hello {
    public function sayHello() {
    echo 'Hello ';
    }
    } trait World {
    public function sayWorld() {
    echo 'World';
    }
    } class MyHelloWorld {
    use Hello, World;
    public function sayExclamationMark() {
    echo '!';
    }
    } $o = new MyHelloWorld();
    $o->sayHello();
    $o->sayWorld();
    $o->sayExclamationMark();
    ?>

    上面的代码会输出:

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAasAAAApCAIAAAAEfJFdAAACvElEQVR4nO3dy3GDMBRA0fRDK2rEM2pEXXijPqjFbiQLBAj0ASTzfffskhBknOGOQIzz9/l83u/36/X6A55MmbZtjTp1D+hc6W9BAQHIRQEByEUBAchFAQHIRQEByEUBAchFAQHIRQEByEUBAchFAQHIRQEByEUBAchFAQHIRQEByEUBAchFAQHIRQEByEUBAchFAQHItVMBlWmn5h/pv7jBLZQcRaPtXQ8XeBwKWOOXBWy0bVurm11eKICo/a+CF+c8z5gUrT4KCghcx/f7DQoY+U90FZU6p4DKJHeZ+VEFCgjc0JMLmMiJMnuEhgICN1RTQP8uWPrUrSlg96OSW4WNtpl9ej/IDuG9NP9gY/vNHeb4u1Y3FBC4jtICTsORi2BxAYNlhk0V9CeByrTTL/q9LA3hXpqeHeyWAkbeqPguKCBwvLICutN63KZLSWYet7mALk5jEtyYaxvhTQInu2q07fexPMSYr+F7qbuIicPsxhj32DeXAgJXkCxgbuISOVnT529ZAWNJ7TZcG4lhEjhkbLia9cOYHSIofVqm45F3igICl1BUwMUNfBUFnPdg05rJMNlTprVaua/mU8D8EBsGjG4a+2Zyn/usUQPIKLoKvkUB+6K4lQ83JfQyQwEB8coLuOmG3AlXwa55yi39dvcF9TgFXH8VfFABARyubCXETQKD813/bA5YvRLSN88YfwnEGBscxeJKSHkBgxuJ03uSAE5W+jRM/EL4d1fBqSG2lGNWuCB4q5+GKS9g+DCMNSa3IUshwJF+9UR0+uQ954lo77dnc77ohWpiiPoCTkfo12IoIHANsQICgAwUEIBcFBCAXBQQgFzZAiY/AvkZn/B8B5FVqUcK18wzS0KNtqwY4Td2L2D80cFLWfiUr8nJWXzmFb4PhxVw+ieNjOi/DXt9wOxyAeueDgBm/gHMH9X2J7bOCAAAAABJRU5ErkJggg==" alt="" />

  • 示例4 冲突的解决 

    如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。

    为了解决多个 trait 在同一个类中的命名冲突,需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。

    <?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;
    }
    }
    ?>
  • 示例5  使用trait来组成trait   正如 class 能够使用 trait 一样,其它 trait 也能够使用 trait。在 trait 定义时通过使用一个或多个 trait,能够组合其它 trait 中的部分或全部成员。
    <?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();
    ?>

    上面例子会输出:

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAasAAAApCAIAAAAEfJFdAAACvElEQVR4nO3dy3GDMBRA0fRDK2rEM2pEXXijPqjFbiQLBAj0ASTzfffskhBknOGOQIzz9/l83u/36/X6A55MmbZtjTp1D+hc6W9BAQHIRQEByEUBAchFAQHIRQEByEUBAchFAQHIRQEByEUBAchFAQHIRQEByEUBAchFAQHIRQEByEUBAchFAQHIRQEByEUBAchFAQHItVMBlWmn5h/pv7jBLZQcRaPtXQ8XeBwKWOOXBWy0bVurm11eKICo/a+CF+c8z5gUrT4KCghcx/f7DQoY+U90FZU6p4DKJHeZ+VEFCgjc0JMLmMiJMnuEhgICN1RTQP8uWPrUrSlg96OSW4WNtpl9ej/IDuG9NP9gY/vNHeb4u1Y3FBC4jtICTsORi2BxAYNlhk0V9CeByrTTL/q9LA3hXpqeHeyWAkbeqPguKCBwvLICutN63KZLSWYet7mALk5jEtyYaxvhTQInu2q07fexPMSYr+F7qbuIicPsxhj32DeXAgJXkCxgbuISOVnT529ZAWNJ7TZcG4lhEjhkbLia9cOYHSIofVqm45F3igICl1BUwMUNfBUFnPdg05rJMNlTprVaua/mU8D8EBsGjG4a+2Zyn/usUQPIKLoKvkUB+6K4lQ83JfQyQwEB8coLuOmG3AlXwa55yi39dvcF9TgFXH8VfFABARyubCXETQKD813/bA5YvRLSN88YfwnEGBscxeJKSHkBgxuJ03uSAE5W+jRM/EL4d1fBqSG2lGNWuCB4q5+GKS9g+DCMNSa3IUshwJF+9UR0+uQ954lo77dnc77ohWpiiPoCTkfo12IoIHANsQICgAwUEIBcFBCAXBQQgFzZAiY/AvkZn/B8B5FVqUcK18wzS0KNtqwY4Td2L2D80cFLWfiUr8nJWXzmFb4PhxVw+ieNjOi/DXt9wOxyAeueDgBm/gHMH9X2J7bOCAAAAABJRU5ErkJggg==" alt="" />

除了这些特性,trait 还包括 抽象成员  静态成员  静态方法  属性 等特性,可以参考    http://php.net/language.oop5.traits

PHP代码的多继承 -》 PHP代码复用新的姿势 trait的更多相关文章

  1. Java面向对象理解_代码块_继承_多态_抽象_接口

    面线对象: /* 成员变量和局部变量的区别? A:在类中的位置不同 成员变量:在类中方法外 局部变量:在方法定义中或者方法声明上 B:在内存中的位置不同 成员变量:在堆内存 局部变量:在栈内存 C:生 ...

  2. Java基础进阶:继承重点摘要,继承详解,方法重写注意事项,方法重载与重写的区别,抽象类,代码块, 附重难点,代码实现源码,课堂笔记,课后扩展及答案

    继承重点摘要 *继承的特点: 子类在初始化之前,一定要先完成父类数据的初始化 子类在初始化之前,一定要先访问父类构造,完成父类数据的初始化 系统在每一个构造方法中默认隐藏了一句super(); 如果我 ...

  3. Winform打砖块游戏制作step by step第5节---重构代码,利用继承多态

    一 引子 为了让更多的编程初学者,轻松愉快地掌握面向对象的思考方法,对象继承和多态的妙用,故推出此系列随笔,还望大家多多支持. 二 本节内容---重构代码,利用继承多态 1. 主界面截图如下: 2.  ...

  4. Java之同步代码块处理继承Thread类的线程安全问题

    package com.atguigu.java; /** *//** * 使用同步代码块解决继承Thread类的方式的线程安全问题 * * 例子:创建三个窗口卖票,总票数为100张.使用继承Thre ...

  5. final、static、代码块、静态代码块、内部类、代码执行顺序

    final final域使得确保初始化安全性(initialization safety)成为可能,初始化安全性让不可变形对象不需要同步就能自由地被访问和共享 作用在类上               ...

  6. 关于java构造函数,静态代码块,构造代码块,和普通代码块相关总结(一)

    构造函数.构造代码块和静态代码块容易混淆,它们的执行条件和执行顺序也常常容易犯迷.这里就针对这些问题说一下我个人的一些理解,顺便对这部分内容做个小结. 一.构造函数 格式:类名(参数1,参数2,-){ ...

  7. java代码编译与C/C++代码编译的区别

    Java编译原理 1.Java编译过程与c/c++编译过程不同 Java编译程序将java源程序编译成jvm可执行代码--java字节码. Java在编译过程中一般会按照以下过程进行: (1)JDK根 ...

  8. Swagger结合mustache模板生成后台接口代码、以及前后台建模代码

    之前项目中使用的的thrift来建模,维护前后台模型以及rest接口,前台使用的是angular2: 但是使用thrift只能生成建模,后台的rest接口的Controller文件还是需要手动去写,一 ...

  9. Web前端开发最佳实践(9):CSS代码太太乱,重复代码太多?你需要精简CSS代码

    前言 提高网站整体加载速度的一个重要手段就是提高代码文件的网络传输速度.之前提到过,所有的代码文件都应该是经过压缩了的,这可提高网络传输速度,提高性能.除了压缩代码之外,精简代码也是一种减小代码文件大 ...

随机推荐

  1. 宏定义中的反斜杠"\"和宏定义的细节说明

    转载自:http://www.wtoutiao.com/p/K6csca.html 在阅读C语言代码经常可以看到代码中出现反斜杠"\",不是很明白它的意思,遂对反斜杠"\ ...

  2. 流畅的python和cookbook学习笔记(七)

    1.读写压缩数据文件 使用 gzip 和 bz2 模块来读写压缩文件,不过需要注意文件的模式,默认格式为二进制. # 读取压缩文件 import gzip with gzip.open('somefi ...

  3. java温故而知新(8)反射机制

    一.什么是反射机制  简单的来说,反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息. 二.哪里用到反射机制  有些时候,我们用过 ...

  4. SQL Join 语句

    SQL Join 语句 SQL 中每一种连接操作都包括一个连接类型和连接条件. 连接类型 决定了如何处理连接条件不匹配的记录. 连接类型 返回结果 inner join 只包含左右表中满足连接条件的记 ...

  5. 终止ajax请求

    在做搜索功能时,文本框输入文本就得请求一次数据,如果上一次的请求还没回又请求了就导致数据错误和无用的数据请求. 我们需要输入文本时候判断上一次的ajax请求是否完毕,若还没完毕就终止本次请求. 对于j ...

  6. safari兼容时间格式

    前提: 使用iview的DatePicker组件,保存时间后台接收时间戳 问题: safari中不支持2018-02-13这种格式转为时间戳会显示NaN 解决: new Date('2018/02/1 ...

  7. 20.远程分支&跟踪分支

    远程分支 远程引用是对远程仓库的引用(指针),包括分支.标签等等. 你可以通过 git ls-remote (remote) 来显式地获得远程引用的完整列表,或者通过 git remote show ...

  8. google离线小恐龙-备份

    开启方法: 地址栏输入: chrome://dino 空格开始

  9. 【Leetcode】【Medium】Path Sum II

    Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given su ...

  10. [使用经验]cocostudio UI编辑器的裁剪

    日志-2015/03/16 描述:在程序使用UI编辑器导出文件的时候,该panel中大于panel的部分都没有显示出来,例如人物,一些特效等 原因:UI编辑器panel都勾上了裁剪 解决:在编辑器中把 ...