trait
引文
在php中,为实现代码复用,有了继承,但是一个类只能继承一个父类,不支持多继承,接口支持多实现,但是接口又不太一样,接口对外负责功能调用声明,不负责实现,由实现了接口的类去实现具体功能逻辑,严格意义上来说,不算代码复用,从php5.4开始,php实现了另外一种代码复用的方法,就是下文即将要说的trait。
trait
trait是为扩展类似php单继承的一种代码复用机制,解除单继承语言的限制,使开发人员能够自由地在不同层次结构中组合复用method。trait本身不能实例化,它依托于class存在。传统继承是上下层面的关系,trait则为水平层面的组合。
优先级
对于相同方法名的方法而言,当前类的方法覆盖trait方法,trait中方法覆盖继承的父类方法
class Base {
public function sayHello() {
echo 'Hello ';
}
} trait SayWorld {
public function sayHello() {
parent::sayHello();
echo 'World!';
} public function sayPeter() {
echo "\nhello trait peter\n";
}
} class MyHelloWorld extends Base {
use SayWorld;
public function sayPeter() {
echo "\nhello class peter\n";
}
} $o = new MyHelloWorld();
$o->sayHello();
$o->sayPeter();
输出
多个trait
在类中,可以声明多个trait,将多个trait组合到一个类中
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();
输出
trait冲突
如果trait之间定义了同名的方法,类中又组合了有同名方法的trait,会出现命名冲突,这个时候可以使用insteadof指明调用冲突方法中的某一个。trait中可以用as操作符为某个方法引入别名,注意引入别名并不会对原方法重命名,别名不能和已包含的trait中方法名重复
trait A {
public function smallTalk() {
echo 'a';
}
public function bigTalk() {
echo 'A';
}
public function helloPeter() {
echo "hello peter\n";
}
} trait B {
public function smallTalk() {
echo 'b';
}
public function bigTalk() {
echo 'B';
}
public function helloAlice() {
echo "hello alice\n";
}
} class Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
}
} class TalkerAs {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
B::bigTalk as talk;
}
} class TalkerHello {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
// A::helloPeter as helloAlice; 别名不允许和已包含trait中方法重名
}
} $talker = new Talker();
$talker->smallTalk();
$talker->bigTalk();
echo "\n";
$talkerAs = new TalkerAs();
$talkerAs->smallTalk();
$talkerAs->bigTalk();
$talkerAs->talk();
输出
trait组合trait
正如class可以使用多个trait,trait也可以使用trait
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();
输出
抽象成员方法
在trait中可以定义抽象方法,类中如果要使用trait,必须要实现trait中的抽象方法
trait Hello {
public function sayHelloWorld() {
echo 'Hello ' . $this->getWorld() . "\n";
}
abstract public function getWorld();
} class MyHelloWorld {
private $world;
use Hello;
public function getWorld() {
return $this->world;
}
public function setWorld($val) {
$this->world = $val;
}
} $o = new MyHelloWorld();
$o->sayHelloWorld();
$o->setWorld('world');
$o->sayHelloWorld();
输出
属性
trait中也可以定义属性,但要注意trait定了某个属性后,使用该trait的类中就不能定义同样名称的属性,否则会产生fatal error。(属性如果是兼容的(同样的访问控制符和默认值),就不会产生fatal error,但在php7之前,会有E_STRICT提醒)
trait PropertiesTrait {
public $same = true;
public $different = false;
} class PropertiesExample {
use PropertiesTrait;
public $same = true; // PHP 7.0.0 后没问题,之前版本是 E_STRICT 提醒
public $different = true; // 致命错误
}
php5.6
php7.1
trait的更多相关文章
- php中trait(性状)与generator(生成器)
PHP中trait(性状)与generator(生成器) 一.trait (性状) 最近在看Josh Lockhat的<Modern PHP>,这本书很薄.但是其中给出了一个很重要的学习方 ...
- 【转】PHP的Trait 特性
Trait是在PHP5.4中加入的,它既不是接口也不是类.主要是为了解决单继承语言的限制.是PHP多重继承的一种解决方案.例如,需要同时继承两个 Abstract Class, 这将会是件很麻烦的事情 ...
- Beginning Scala study note(7) Trait
A trait provides code reusability in Scala by encapsulating method and state and then offing possibi ...
- 速战速决 (4) - PHP: 类基础, 抽象类, 接口, trait
[源码下载] 速战速决 (4) - PHP: 类基础, 抽象类, 接口, trait 作者:webabcd 介绍速战速决 之 PHP 类基础 抽象类 接口 trait 示例1.类的相关知识点 1(基础 ...
- Scala的trait
一:说明 1.介绍 2.功能 二:具体解释功能 1.定义接口 2.定义方法 3.定义字段 4.定义抽象字段 5.混合trait
- 利用GCTA工具计算复杂性状/特征(Complex Trait)的遗传相关性(genetic correlation)
如文章"Genome-wide Complex Trait Analysis(GCTA)-全基因组复杂性状分析"中介绍的GCTA,是一款基于全基因组关联分析发展的分析工具,除了计算 ...
- PHP中Trait特性
Trait是自 PHP 5.4.0 起添加的一个新特性,是 PHP 多重继承的一种解决方案.例如,需要同时继承两个 Abstract Class, 这将会是件很麻烦的事情,Trait 就是为了解决这个 ...
- scala 学习笔记(05) OOP(中)灵活的trait
trait -- 不仅仅只是接口! 接上回继续,scala是一个非常有想法的语言,从接口的设计上就可以发现它的与众不同.scala中与java的接口最接近的概念是trait,见下面的代码: packa ...
- Scala Trait
Scala Trait 大多数的时候,Scala中的trait有点类似于Java中的interface.正如同java中的class可以implement多个interface,scala中的cals ...
- scala中的trait
这里的trait字面意思是特质或者特征,这个词翻译成特征比较合适.它的意义和java,c#中接口很类似.但是trait支持部分实现,也就是说可以在scala的trait中可以实现部分方法. 下面我们以 ...
随机推荐
- 【动态规划】洛谷P1006传纸条
题目描述: 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运的 ...
- ssh框架实现员工部门增删改查源码
http://pan.baidu.com/s/1qYLspDM 备注:IDE是eclipse,前端使用bootstrap,数据库是mysql
- HashSet源码阅读
HashSet的实现基于HashMap 看几个简单的初始化方法 public HashSet() { map = new HashMap<>(); } public HashSet(Col ...
- 你不知道的JSON.stringify和JSON.parse
json是JavaScript 对象表示法(JavaScript Object Notation),是一种简单的数据格式,类似于XML,其格式为名称/值对,数据用逗号隔开,名称必须用双引号括起来.例如 ...
- POJ 3673 Cow Multiplication
Cow Multiplication Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13312 Accepted: 93 ...
- 2017"百度之星"程序设计大赛 - 复赛1005&&HDU 6148 Valley Numer【数位dp】
Valley Numer Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- Codeforces 810C Do you want a date?(数学,前缀和)
C. Do you want a date? time limit per test:2 seconds memory limit per test:256 megabytes input:stand ...
- Gym101522A Gym101522C Gym101522D
Gym101522A A There are two popular formats for representing a date: day/month/year or month/day/year ...
- android银行卡匹配、详情展开动画、仿爱奇艺视频拖拽、扫码识别手机号等源码
Android精选源码 android实现银行卡匹配信息源码 android实现可以展开查看详情的卡片 下拉刷新,上拉加载,侧滑显示菜单等效果RefreshSwipeRecyclerview andr ...
- 大白话说Java泛型(二):深入理解通配符
文章首发于[博客园-陈树义],点击跳转到原文<大白话说Java泛型(二):深入理解通配符> 上篇文章<大白话说Java泛型(一):入门.原理.使用>,我们讲了泛型的产生缘由以及 ...