本文参考:  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. 理解Xaml标记语言

    理解XAML XAML基于XAML,因而具有与XAML相似的特性.在XAMl中,同样必须区分大小写,但是Xaml以.xaml作为扩展名,表示这是一个应用程序的标记扩展文件.WPF中的XAML主要用于创 ...

  2. Silverlight & Blend动画设计系列九:动画(Animation)与视图状态管理(Visual State Manager)

    Silverlight中的动画(Animation)与视图状态管理(Visual State Manager) 结合使用是非常常见的,动画用于管理对象在某段事件段内执行的动画动作,视图状态管理则用于控 ...

  3. MVC 下拉框联动效果(单选)

    下拉框联动效果,我们以部门--职位为例,选择部门时,关联到该部门的职位.下拉框的写法就不多说了,详细请参照前文. 视图: 其中,dept是部门的属性,deptlist是部门下拉框的属性,job是职位的 ...

  4. js 表格合并单元格

    5列  根据需要可添加 或 删除 strOneTemp  strTwoTemp  strThreeTemp  strFourTemp  strFiveTemp //合并单元格  this.mergeC ...

  5. JavaScript--3种函数调用的方法

    1.函数的简单调用: <script > function fn(p){ alert(p); } </script> <body><script> fn ...

  6. jvm内置锁synchronized不能被中断

    很久没看技术书籍了,今天看了一下<七周七并发模型>前面两章讲的java,写的还是有深度的.看到了一个有demo,说jvm内置锁synchronized是不能被中断的.照着书上写了个demo ...

  7. ubuntu 16.10安装nginx

    1 : cd /usr/local 2 : sudo wget http://nginx.org/download/nginx-1.2.8.tar.gz 3 : sudo tar -zxvf ngin ...

  8. 子级用css float浮动 而父级不能自适应高度解决方法

    解决子级对象使用css float浮动 而父级div不能自适应高度,不能被父级内容撑开解决方法,父级div没有高度解决方法. 当在对象内的盒子使用了float后,导致对象本身不能被撑开自适应高度,这个 ...

  9. HTML 发表说说 制作方法

    ==================================================================================================== ...

  10. FCKeditor文本编辑器的使用方法

    FCKeditor是一个功能强大支持所见即所得功能的文本编辑器,可以为用户提供微软office软件一样的在线文档编辑服务. 它不需要安装任何形式的客户端,兼容绝大多数主流浏览器,支持ASP.Net.A ...