trait
- PHP
- /**
- * Created by PhpStorm.
- * User: YANGHY
- * Date: 2020/4/29
- * Time: 10:21
- */
- /**
- * Class TestTrait
- * Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制.
- * Trait 为了减少单继承语言的限制, 在不同层次结构内独立的类中复用 method.
- * Trait 和 Class 相似, 但仅仅旨在用细粒度和一致的方式来组合功能. 无法通过 trait 自身来实例化.
- * 优先顺序是当前类中的方法会覆盖 trait 方法, 而 trait 方法又覆盖了基类中的方法.
- *
- */
- // 例子 1 单个 trait 的使用
- /**trait TraitExample{
- public function add($a,$b){
- return $a + $b;
- }
- public function sub($a, $b){
- return $a - $b;
- }
- }
- class TestTrait
- {
- use TraitExample; // 使用 trait
- }
- $obj = new TestTrait();
- echo $obj->add(10,12)."\n";
- echo $obj->sub(12,2);**/
- // 例子 2 优先级
- //trait TraitExample{
- // public function add($a,$b){
- // return $a + $b;
- // }
- // public function sub($a, $b){
- // return $a - $b;
- // }
- //}
- //class Count{
- // public function add($a,$b){
- // return $a + $b + 100;
- // }
- // public function sub($a, $b){
- // return $a - $b + 100;
- // }
- //}
- //class TestTrait extends Count
- //{
- // public function add($a,$b){
- // return $a + $b + 200;
- // }
- // public function sub($a, $b){
- // return $a - $b + 200;
- // }
- // use TraitExample; // 使用 trait
- //}
- //$obj = new TestTrait();
- //echo $obj ->add(10,10)."\n"; // 220
- //echo $obj ->sub(10,10); // 200
- // 例子 3 多个 trait 通过逗号分隔, 在 use 声明列出多个 trait, 可以都插入到一个类中.
- /*trait Ex1{
- public function say(){
- echo "hello";
- }
- }
- trait Ex2{
- public function reply(){
- echo "hi";
- }
- }
- class Test{
- use Ex1,Ex2; // 引用多个 trait
- }
- $obj = new Test();
- $obj ->say();
- echo "\n";
- $obj ->reply();*/
- // 4. 多个 trait 中同名函数冲突解决方法
- // insteadof 明确使用哪一个
- /*trait Ex1{
- public function say(){
- echo "Ex1 say hello";
- }
- public function replay(){
- echo "Ex1 reply hi";
- }
- }
- trait Ex2{
- public function say(){
- echo "Ex2 say hello";
- }
- public function replay(){
- echo "Ex2 reply hi";
- }
- }
- class Test{
- use Ex1,Ex2{
- Ex2::say insteadof Ex1; // 使用 insteadof 明确使用哪个 例如使用 Ex2 的 say
- Ex1::replay insteadof Ex2; // 使用 Ex1 的 replay
- } // 引用多个 trait
- }
- $obj = new Test();
- $obj ->say(); // Ex2 say hello
- echo "\n";
- $obj ->replay(); // Ex1 reply hi*/
- // as 引入别名
- /*trait Ex1{
- public function say(){
- echo "Ex1 say hello";
- }
- public function replay(){
- echo "Ex1 reply hi";
- }
- }
- trait Ex2{
- public function say(){
- echo "Ex2 say hello";
- }
- public function replay(){
- echo "Ex2 reply hi";
- }
- }
- class Test{
- use Ex1,Ex2{
- Ex1::say insteadof Ex2;
- Ex1::replay insteadof Ex2;
- Ex2::say as Esay;
- Ex2::replay as Ereplay;
- } // 引用多个 trait
- }
- $obj = new Test();
- $obj ->say(); // Ex1 say hello
- echo "\n";
- $obj ->replay(); // Ex1 reply hi
- echo "\n";
- $obj ->Esay(); // Ex2 say hello
- echo "\n";
- $obj ->Ereplay(); // Ex2 say hi*/
- // 修改方法的访问控制权限
- /*trait Control{
- public function getC(){
- echo "public";
- }
- }
- class Test{
- use Control{
- // getC as private; // 修改方法权限
- getC as private getByC;// 原版 getC 的访问控制并没有发生变化, 生成的新的 getByC 控制权限为 private
- }
- public function getControl($className,$method){
- $reflection = new ReflectionMethod($className,$method);
- $result = Reflection::getModifierNames($reflection->getModifiers());
- print_r($result);
- }
- }
- //
- $obj = new Test();
- // Array
- // (
- // [0] => private
- // )
- $obj ->getControl('Test','getC');
- $obj ->getControl('Test','getbyC');
- */
- //trait 组成 trait
- /*trait Hello{
- public function hello(){
- echo "hello";
- }
- }
- trait World{
- public function world(){
- echo "world";
- }
- }
- trait HelloWorld{
- use Hello,World;
- }
- class MyHelloWorld{
- use HelloWorld;
- }
- $obj = new MyHelloWorld();
- $obj ->hello();
- echo " ";
- $obj ->world();*/
- //trait 的抽象成员 为了对使用的类强制要求, trait 支持抽象方法的使用
- /*trait Hello{
- public function sayHello(){
- echo "hello".$this->getWorld();
- }
- abstract function getWorld();
- }
- class Test{
- use Hello;
- private $world;
- function getWorld()
- {
- return $this->world;
- }
- function setWorld($value){
- $this ->world = $value;
- }
- }
- $obj = new Test();
- $obj ->setWorld("world!");
- $obj ->sayHello();*/
- // trait 可以被静态成员和静态方法定义
- /*trait StaticVf{
- static $a = 'kral';
- static public function say(){
- echo "今天的天气可真好!";
- }
- }
- class Test{
- use StaticVf;
- }
- echo Test::$a;
- Test::say();*/
- // trait Trait 定义了一个属性后, 类就不能定义同样名称的属性, 否则会产生 fatal error.
- // 有种情况例外: 属性是兼容的 (同样的访问可见度, 初始默认值). 在 PHP 7.0 之前, 属性是兼容的, 则会有 E_STRICT 的提醒.
- /*trait StaticV{
- public $a = true;
- public $b = false;
- }
- class Test{
- use StaticV;
- public $a = "hello"; // Fatal error 测试版本 PHP 7.3.1
- public $b = false; // PHP 7.0.0 后没问题, 之前版本是 E_STRICT 提醒
- }
- $obj = new Test();*/
- // 与继承不同; 如果 trait 具有静态属性, 则使用该 trait 的每个类都具有这些属性的独立实例.
- // 继承
- /*class StaticV{
- static $a;
- }
- class TestStaticv extends StaticV{
- }
- class TestStaticv2 extends StaticV{
- }
- TestStaticv::$a = 'hello';
- TestStaticv2::$a = 'world';
- echo TestStaticv::$a.' '.TestStaticv2::$a; // World World*/
- /*trait StaticV{
- static $a;
- }
- class TestTrait{
- use StaticV;
- }
- class TestTrait2{
- use StaticV;
- }
- TestTrait::$a = 'hello';
- TestTrait2::$a = 'world';
- echo TestTrait::$a.' '.TestTrait2::$a; // hello world*/
- // __CLASS__ 返回使用 trait 的类的名称, 不是调用 trait 方法的类
- /*trait MyTrait{
- public function TestTrait(){
- echo "CLASS:".__CLASS__;
- echo "TRAIT:".__TRAIT__;
- }
- }
- class BaseClass{
- use MyTrait;
- }
- class TestBaseClass extends BaseClass{
- }
- $obj = new TestBaseClass();
- $obj ->TestTrait();*/
- // Traits 与继承的另一个区别是, Traits 中定义的方法可以访问它们使用的类的方法和属性, 包括私有类.
- /*trait MyTrait{
- protected function setVar(){
- return $this ->var;
- }
- }
- class TraitUser{
- use MyTrait;
- private $var = 'var';
- public function getVar()
- {
- return $this ->setVar($this->var);
- }
- }
- $obj = new TraitUser();
- echo $obj->getVar();*/
- // 如前所述, trait 中的静态属性和方法可以使用 trait 直接访问. 由于 trait 是语言辅助的 c/p,
- // 您应该注意, trait 中的静态属性将被初始化为 trait 属性在类声明时的值.
- /*trait Base{
- protected static $a = 'Right';
- public static function printed(){
- echo static::$a.PHP_EOL;
- }
- public static function setType($value){
- static::$a = $value;
- }
- }
- class Test{
- use Base;
- }
- Base::setType('Left');
- class Test2{
- use Base;
- }
- Base::setType('Center');
- Base::printed();
- Test::printed();
- Test2::printed();*/
- // 魔术方法__call 按预期工作
- // PHP5 的对象新增了一个专用方法 __call(),
- // 这个方法用来监视一个对象中的其它方法. 如果你试着调用一个对象中不存在或被权限控制中的方法,__call 方法将会被自动调用.
- /*trait Base{
- public function __call($name, $arguments)
- {
- return count($arguments);
- }
- }
- class TestTrait{
- use Base;
- }
- $obj = new TestTrait();
- echo $obj ->go(1,2,3);*/
- // trait 单例
- /*trait Singleton{
- public static function getSingleton(){
- static $singleton = NULL;
- $class = __CLASS__;
- return $singleton?$singleton:new $class;
- }
- public function __clone() {
- trigger_error('Cloning'.__CLASS__.'is not allowed.',E_USER_ERROR);
- }
- public function __wakeup() {
- trigger_error('Unserializing'.__CLASS__.'is not allowed.',E_USER_ERROR);
- }
- }
- class Test{
- use Singleton;
- private function __construct()
- {
- $this ->name ='Test';
- }
- }
- class Test2{
- use Singleton;
- private function __construct()
- {
- $this->name = 'Test2';
- }
- }
- $test = Test::getSingleton();
- var_dump($test);
- //$test11 = Test::getSingleton();
- //var_dump($test11);
- echo $test->name;
- $test2 = Test2::getSingleton();
- echo $test2 ->name;
- var_dump($test2);*/
- trait
来源: http://www.bubuko.com/infodetail-3529880.html