概述

traits是PHP5.4新进入的特性,其目的就是解决PHP的类不能多继承的问题。Traits不是类!不能被实例化。可以理解为一组能被不同的类都能调用到的方法集合。只需要在类中使用关键词use引入即可,可引入多个Traits,用','隔开。

简单使用

trait myTrait{

    public $traitPublic = 'public';
protected $traitProtected = 'protected'; function traitMethod1()
{
echo __METHOD__,PHP_EOL;
} function traitMethod2()
{
echo __METHOD__,PHP_EOL;
}
} class myClass{
use myTrait;
} $obj = new myClass();
$obj->traitMethod1();
$obj->traitMethod2(); // ↓↓ 只能调用public的属性和方法; protected以及private只供在traits内部自己调用;
echo $obj->traitPublic;

优先级问题

Trait会覆盖继承的方法,当前类会覆盖Trait方法。即 继承的方法 < Traits方法 < 当前类方法,

trait A{
public $var1 = 'test'; public function test()
{
echo 'A::test()';
} public function test1()
{
echo 'A::test1()';
}
} class B{
public function test()
{
echo 'B::test()';
} public function test1()
{
echo 'B::test1()';
}
} class C extends B{
use A; public function test()
{
echo 'c::test()';
}
} $c = new C();
$c->test(); //c::test() Traits方法 < 当前类方法
$c->test1(); //A::test1() 继承的方法 < Traits方法

多个Trait冲突问题

  1. 如果两个 trait 都插入了一个同名的方法,如果没有明确解决冲突将会产生一个致命错误。
  2. 为了解决多个 trait 在同一个类中的命名冲突,需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个。
  3. 可用as操作符将其中一个冲突方法另起名;
trait A{
public function test()
{
echo 'A::test()';
}
} trait B{
public function test()
{
echo 'B::test()';
}
} class C{
use A , B {
B::test insteadof A; //明确B替代A
B::test as t; //或者另起一个名字
}
} $c = new C();
$c->test(); //B::test()
$c->t(); //B::test() 可以用as另起名

as可用来修改方法访问控制

trait  HelloWorld{
public function sayHello()
{
echo 'Hello World!';
}
} // 修改 sayHello 的访问控制
class A{
use HelloWorld {
sayHello as protected;
}
} // 给方法一个改变了访问控制的别名
// 原版 sayHello 的访问控制则没有发生变化
class B{
use HelloWorld {
sayHello as private myPrivateHello;
}
} $a = new A();
$a->sayHello(); //Fatal error: Call to protected method A::sayHello() from context ''; 改变了sayHello的访问规则; $b = new B();
$b->sayHello(); //Hello World!

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(); // Hello World!

Trait中抽象成员

为了对使用的类施加强制要求,trait 支持抽象方法的使用。

trait Hello{
public function sayHelloWorld()
{
echo 'Hello' . $this->getWorld();
} abstract public function getWorld();
} class MyHelloWorld{
private $world;
use Hello; // 必须要实现trait里面的抽象方法,否则Fatal error: Class MyHelloWorld contains 1 abstract method and must therefore be declared abstract or implement the remaining methods
public function getWorld()
{
return $this->world;
} public function setWorld($val)
{
$this->world = $val;
}
} $obj = new MyHelloWorld();
echo $obj->setWorld();

Trait中静态成员

Traits 可以被静态成员静态方法定义,不可以直接定义静态变量,但静态变量可被trait方法引用.

# 静态属性;
trait Counter {
public function inc() {
static $c = 0;
$c = $c + 1;
echo "$c\n";
}
} class C1 {
use Counter;
} class C2 {
use Counter;
} $o = new C1();
$o->inc(); // echo 1
$o->inc(); // echo 2; $p = new C2();
$p->inc(); // echo 1 # 静态方法
trait StaticExample {
public static function doSomething() {
echo 'Doing something';
}
} class Example {
use StaticExample;
} Example::doSomething(); // Doing something

Trait中属性

trait PropertiesTrait{
public $x = 1;
} class PropertiesExample{
use PropertiesTrait;
} $example = new PropertiesExample;
echo $example->x; // 1

如果 trait 定义了一个属性,那类将不能定义同样名称的属性,否则会产生一个错误。如果该属性在类中的定义与在 trait 中的定义兼容(同样的可见性和初始值)则错误的级别是 E_STRICT,否则是一个致命错误。

trait PropertiesTrait {
public $same = true;
public $different = false;
} class PropertiesExample {
use PropertiesTrait;
public $same = true; // Strict Standards
public $different = true; // 致命错误
}

参考链接:

http://www.php.net/manual/zh/language.oop5.traits.php

PHP类多继承的替代方案Traits的更多相关文章

  1. #PHP 类的多继承实现之 traits.md

    TRAIT PHP本身是并不支持多继承的,也就是,一个类只能继承一个类,为了满足业务需求,后来有了一些解决方法,例如,链式继承,B继承A,然后C继承B,这样,C就同时继承了AB, 此外还有接口,因为接 ...

  2. javascript“类”与继承总结和回顾

    Javascipt语法不支持"类"(class)[es6已经支持],但是有模拟类的方法.今天我主要谈谈Javascipt中模拟“类”的方法及js中继承的总结和回顾. js中实现“类 ...

  3. UML类图(上):类、继承和实现

    面向对象设计 对于一个程序员来说,在工作的开始阶段通常都是别人把东西设计好,你来做.伴随着个人的成长,这个过程将慢慢变成自己设计一部分功能来实现,自己实现.如果要自己设计,无论是给自己看,还是给别人看 ...

  4. 【Python五篇慢慢弹(5)】类的继承案例解析,python相关知识延伸

    类的继承案例解析,python相关知识延伸 作者:白宁超 2016年10月10日22:36:57 摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下.官方给 ...

  5. (转)Java:类与继承

    原文地址: http://www.cnblogs.com/dolphin0520/p/3803432.html 对于面向对象的程序设计语言来说,类毫无疑问是其最重要的基础.抽象.封装.继承.多态这四大 ...

  6. iBatis.net 类的继承extends和懒加载

    <resultMaps> <resultMap id="FullResultMap" class="t_c_team_member_permission ...

  7. python 类定义 继承

    0 前言 系统:win7 64bit IDE : python(x,y) 2.7.6.1 IDE集成的解释器:Python 2.7.6 (default, Nov 10 2013, 19:24:18) ...

  8. JS原型继承和类式继承

    前言 一个多月前,卤煮读了一篇翻译过来的外国人写的技术博客.此君在博客中将js中的类(构造)继承和原型继承做了一些比较,并且得出了结论:建议诸位在开发是用原型继承.文中提到了各种原型继承的优点,详细的 ...

  9. Java编程里类的继承

    今天,我们将要讨论的内容是Java里面类的继承的相关概念. 说到继承,我相信大家都不陌生.生活中,子承父业,子女继承父母的财产,这就是继承.实际上,Java里的继承也是如此.对于一个类来说,它的数据成 ...

随机推荐

  1. 【Redis面试题】Redis的字符串是怎么实现的?

    年前本人在找工作面试时在Redis相关问题上可栽了跟头.在面试前按常规套路准备了一下,比如 Redis 的常用5种数据结构,Redis持久化策略,Redis实现分布式锁,简单发布订阅等等都准备了,当时 ...

  2. 第二章 微服务构建:Spring Boot

    此处介绍Spring Boot的目的除了它是Spring Cloud的基础外,也由于其自身的各项优点,如自动化配置.快速开发.轻松部署等,非常适合用作微服务架构中各项具体微服务的开发框架. 本章内容: ...

  3. Spring Cloud Zuul 网关使用与 OAuth2.0 认证授权服务

    API 网关的出现的原因是微服务架构的出现,不同的微服务一般会有不同的服务地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题: 客户端会 ...

  4. jq通过对象获取其ID值,再简单ajax传到后台改值

    <tbody> <tr> <#if scopes?exists> <#list scopes as scopes> <td id='${(scop ...

  5. myeclipse 添加mybatis generator插件

    在红色的方框中输入下面的网址,一直下一步,最后finish即可. https://dl.bintray.com/mybatis/mybatis-generator/

  6. BizTalk Orchestration execute Flat file disassembler ReceivePipeline

    需求是这样,在一个inbound XML中有个一点节点使用平文件的方式存放,还要解析比如固定长度或根据特殊字符截取字段 也就是需要在流程里面先把输入的XML的节点先读出来,这个方式有很多可以直接升级属 ...

  7. [Mysql]——通过例子理解事务的4种隔离级别

    SQL标准定义了4种隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的. 低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销. 首先,我们使用 test 数据库, ...

  8. mysql中的data下的数据文件(.FRM、.MYD、.MYI)恢复为数据

    记一次mysql中的data文件操作经历 想拿到一个项目的最新的数据,做功能升级使用,备份一份数据同时也作为本地测试数据,文件有些大,我直接通过远程的phpmyadmin程序导出,不能愉快的玩耍,直接 ...

  9. U3D MonoBehaviour

    一.简介 MonoBehaviour是每个脚本派生类的基类,它定义了一个脚本文件从最初被加载到最终被销毁的一个完整过程. 这个过程通过对应的方法体现出来,在不同的方法完成不同的功能,我们把这些方法称为 ...

  10. C#检测是否联网

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.R ...