【modernPHP专题(5)】类多继承的替代方案Traits

栏目: PHP · 发布时间: 5年前

内容简介:traits是PHP5.4新进入的特性,其目的就是解决PHP的类不能多继承的问题。Trait会覆盖继承的方法,当前类会覆盖Trait方法。即 继承的方法 < Traits方法 < 当前类方法,为了对使用的类施加强制要求,trait 支持抽象方法的使用。

概述

traits是 PHP 5.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/...


以上所述就是小编给大家介绍的《【modernPHP专题(5)】类多继承的替代方案Traits》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Python for Everyone

Python for Everyone

Cay S. Horstmann、Rance D. Necaise / John Wiley & Sons / 2013-4-26 / GBP 181.99

Cay Horstmann's" Python for Everyone "provides readers with step-by-step guidance, a feature that is immensely helpful for building confidence and providing an outline for the task at hand. "Problem S......一起来看看 《Python for Everyone》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具