PHP Trait 使用指南

PHPer 2023-07-28 385 0 0

通过更好地组织代码和代码复用来最大程度地减少代码重复是面向对象编程的重要目标。但是在 PHP 中,由于使用单一继承模型的局限性,有些时候要做到这些可能会比较困难。您可能有一些要在多个类中使用的方法,但它们可能不太适合继承层次结构。

诸如 C ++ 和 Python 之类的语言允许我们从多个类继承,这在某种程度上解决了这一问题,而 Ruby 中的 mixin 则允许我们混合一个或多个类的功能而无需使用继承。但是多重继承存在诸如钻石问题之类的问题,而 mixin 则能是一个复杂的工作机制。

在本文中我打算探讨一下 Trait,这是一个出现在 PHP 5.4 版本中的新特性,可以用来解决此类问题。Trait 的概念本身对编程而言并非什么新鲜事物,而且在其他语言(例如 Scala 和 Perl)中也已经被使用。它允许我们在不同类层次结构中的各个独立类之间水平地重用代码。

Trait 长什么样

Trait 与抽象类类似,自身无法实例化。PHP 文档对 Trait 的描述如下:

Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。

考虑以下的例子:

<?php

class DbReader extends Mysqli

{

}

class FileReader extends SplFileObject

{

}

当不同类都用到一些相同功能时就会出问题。例如,几个类都需要生成单例,由于 PHP 不支持多继承,那么只能在每个类重复编写代码,或者说将单例功能写在父类中并让这几个类都继承这个父类,这种继承是无意义的。Trait 提供了这类问题的解决方案。

<?php
trait Singleton
{
    private static $instance;

    public static function getInstance() {
        if (!(self::$instance instanceof self)) {
            self::$instance = new self;
        }
        return self::$instance;
    }
}

class DbReader extends ArrayObject
{
    use Singleton;
}

class  FileReader
{
    use Singleton;
}

SingletonTrait 直接实现了单例模式。该 Trait 通过getInstance()静态方法创建并返回使用该 Trait 的类的实例(如果实例还没有创建)。

让我们试着用getInstance()方法创建这些类的对象:

<?php
$a = DbReader::getInstance();
$b = FileReader::getInstance();
var_dump($a);  //object(DbReader)
var_dump($b);  //object(FileReader)

我们可以看到$a是DbReader的实例,$b是FileReader的实例,但是它们现在都有了实现单例的能力。 通过Singleton这个 Trait,它里边的方法已经被水平注入类中。

Trait 不会对类施加任何额外的影响。在某种程度上,你可以将其看作是编译器辅助的复制和粘贴机制,trait 中的方法会被复制到组成类中。

如果我们只是从具有私有属性$instance的父类中将类DbReader子类化, 属性不会被显示在通过ReflectionClass::export()导出的备份中。有了 trait,你就能实现之!

Class [  class FileReader ] {
  @@ /home/shameer/workplace/php54/index.php 19-22

  - Constants [0] {
  }
  - Static properties [1] {
    Property [ private static $_instance ]
  }
  - Static methods [1] {
    Method [  static public method instance ] {
      @@ /home/shameer/workplace/php54/index.php 6 - 11
    }
  }
  - Properties [0] {
  }
  - Methods [0] {
  }
}

多个 Trait

到目前为止我们在在一个类中只用了一个 trait,但在某些情况下,我们可能需要合并多个 trait 的功能。

<?php
trait Hello
{
    function sayHello() {
        echo "Hello";
    }
}

trait World
{
    function sayWorld() {
        echo "World";
    }
}

class MyWorld
{
    use Hello, World;
}

$world = new MyWorld();
echo $world->sayHello() . " " . $world->sayWorld(); //Hello World

在上边的例子中,我们有两个 trait:Hello和World。 TraitHello输出 “Hello” ,而 traitWorld输出 “World”。在类MyWorld中我们引入Hello和World两个 trait ,以便MyWorld类的对象拥有前边两个 trait 的方法,输出 “Hello World”。

Traits 构成的 Traits

随着应用的增长,我们很可能会有一套可用于不同类的 traits 。PHP 5.4 允许我们拥有由其他 traits 构成的 traits 因此我们可以在所有这些类中只包含一个 traits 而不是多个 traits。 这使我们可以重写前一个例子,如下:

<?php
trait HelloWorld
{
    use Hello, World;
}

class MyWorld
{
    use HelloWorld;
}

$world = new MyWorld();
echo $world->sayHello() . " " . $world->sayWorld(); //Hello World

在此我们创建了一个 traitHelloWorld,使用了 traits Hello 和 World 然后包含在MyWorld类里。 由于HelloWorldtrait 具有其他两个 traits 的方法,就如同我们自己在类里包含了两个 traits 。...

立即注册
更新于:2023-07-28 21:22:27
    您需要登录后才可以评论。 立即注册
    相关内容

    PHP向js传数组

    软件使用总结

    2018年必须要吐槽下迅雷,开了迅雷网页打开很慢

    PHP与APP

    PHP是否可以应用于App开发

    【PHP】COOKIE和SESSION的使用以及区别

    推荐内容

    分享几个好用的bt搜索bt资源下载网址网站

    影视电影剧集动漫综艺bt资源在线播放网址网站推荐分享

    全网最新bt磁力搜索引擎bt资源bt网站网址分享

    人气美女女优百度指数排行榜(波多野结衣,苍井空,三上悠亚,深田咏美,桥本有菜,北条...

    最强人造人深田咏美,业界的社交女王

    人生起起落落的三上悠亚,成名前的清纯风,怎么搭配出来的?

    业内第一大长腿,桥本有菜的腿究竟有多长

    波多野结衣,岛国业界著作最多的超级劳模

    日本AV界NO.1,苍井空是多少宅男的疯狂?

    美女女优视频混剪 This Girl-Laza Morgan

    怎样使用V2Ray代理和SSTap玩如魔兽世界/绝地求生/LOL台服/战地3/黑色沙漠/彩...

    sstap游戏代理教程 从此玩如魔兽世界/绝地求生/LOL台服/战地3/黑色沙漠/彩虹六...

    影视电影剧集动漫综艺bt资源在线播放网址网站推荐分享