PHP代码的多继承 -》 PHP代码复用新的姿势 trait
本文参考: 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的更多相关文章
- Java面向对象理解_代码块_继承_多态_抽象_接口
面线对象: /* 成员变量和局部变量的区别? A:在类中的位置不同 成员变量:在类中方法外 局部变量:在方法定义中或者方法声明上 B:在内存中的位置不同 成员变量:在堆内存 局部变量:在栈内存 C:生 ...
- Java基础进阶:继承重点摘要,继承详解,方法重写注意事项,方法重载与重写的区别,抽象类,代码块, 附重难点,代码实现源码,课堂笔记,课后扩展及答案
继承重点摘要 *继承的特点: 子类在初始化之前,一定要先完成父类数据的初始化 子类在初始化之前,一定要先访问父类构造,完成父类数据的初始化 系统在每一个构造方法中默认隐藏了一句super(); 如果我 ...
- Winform打砖块游戏制作step by step第5节---重构代码,利用继承多态
一 引子 为了让更多的编程初学者,轻松愉快地掌握面向对象的思考方法,对象继承和多态的妙用,故推出此系列随笔,还望大家多多支持. 二 本节内容---重构代码,利用继承多态 1. 主界面截图如下: 2. ...
- Java之同步代码块处理继承Thread类的线程安全问题
package com.atguigu.java; /** *//** * 使用同步代码块解决继承Thread类的方式的线程安全问题 * * 例子:创建三个窗口卖票,总票数为100张.使用继承Thre ...
- final、static、代码块、静态代码块、内部类、代码执行顺序
final final域使得确保初始化安全性(initialization safety)成为可能,初始化安全性让不可变形对象不需要同步就能自由地被访问和共享 作用在类上 ...
- 关于java构造函数,静态代码块,构造代码块,和普通代码块相关总结(一)
构造函数.构造代码块和静态代码块容易混淆,它们的执行条件和执行顺序也常常容易犯迷.这里就针对这些问题说一下我个人的一些理解,顺便对这部分内容做个小结. 一.构造函数 格式:类名(参数1,参数2,-){ ...
- java代码编译与C/C++代码编译的区别
Java编译原理 1.Java编译过程与c/c++编译过程不同 Java编译程序将java源程序编译成jvm可执行代码--java字节码. Java在编译过程中一般会按照以下过程进行: (1)JDK根 ...
- Swagger结合mustache模板生成后台接口代码、以及前后台建模代码
之前项目中使用的的thrift来建模,维护前后台模型以及rest接口,前台使用的是angular2: 但是使用thrift只能生成建模,后台的rest接口的Controller文件还是需要手动去写,一 ...
- Web前端开发最佳实践(9):CSS代码太太乱,重复代码太多?你需要精简CSS代码
前言 提高网站整体加载速度的一个重要手段就是提高代码文件的网络传输速度.之前提到过,所有的代码文件都应该是经过压缩了的,这可提高网络传输速度,提高性能.除了压缩代码之外,精简代码也是一种减小代码文件大 ...
随机推荐
- Magento 2中文文档教程 - Magento 2.1.x 系统需求
Magento 2.1.x 系统需求 操作系统 (Linux x86-64) Linux发行版如红帽企业Linux(RHEL),CentOS,Ubuntu,Debian,等等 内存需求 升级的应用程序 ...
- [转]真正了解CSS3背景下的@font face规则
本文转自:http://www.zhangxinxu.com/wordpress/2017/03/css3-font-face-src-local/ by zhangxinxu from http:/ ...
- java 并发 (四) ---- 并发容器
Hashmap 和 Concurrenthashmap Hashmap 不适合并发,应该使用ConcurrentHashMap . 这是很多人都知道的,但是为什么呢? 可以先看一下这两篇文章. JDK ...
- The Struts dispatcher cannot be found. This is usually caused by using Struts tags without the associated filter.
The Struts dispatcher cannot be found. This is usually caused by using Struts tags without the assoc ...
- mongodb-mms安装
mms是mongo集群监控软件. mms非常吃内存,虚拟机测试时,3G内存启动成功一次,之后重启时失败,建议不少于4G内存. MMS下载地址: https://downloads.mongodb.co ...
- Visual Studio Code 的使用
常用快捷键 常用General 按 Press 功能 Function Ctrl + Shift + P,F1 显示命令面板 Show Command Palette Ctrl + P 快速打开 Qu ...
- java下double相乘精度丢失问题
比如 System.out.println(0.14*100); 输出: 14.000000000000002 解决方法: BigDecimal b = new BigDecimal(String.v ...
- laravel验证码
登录验证码 1.首先,进入https://github.com/mewebstudio/captcha,根据captcha上的使用方法一步步来实现验证码的安装,因为是laravel5.7,所以选择了c ...
- 自学git心得-1
Github作为目前世界上最先进的分布式版本控制系统,是软工工作者管理工程代码的不二选择,笔者也是因时所需,自学了基本的git操作,在此回顾一下也作为分享. 推荐学习资源:https://www.li ...
- According to TLD, tag fmt:formatDate must be empty, but is not 问题的解决
在执行jsp格式化后报错,检查下代码,发现变成如下的样式: <fmt:formatDate value="${cur.sa_date}" pattern="yyyy ...