您的位置 首页 php

我们身边的现代PHP(二)

上一篇文章补充:console-demo

一个简单的console-demo项目,包含了psr-4(注意看composer.json文件哟),命名空间配合psr-4,symfony/console组件单独使用(如果需要配合数据库,自行安装自己是熟悉的组件,model和service目录都准备好了的,自己慢慢研究吧)

请慢慢食用:

很少写的性状(trait)

开发中很多人遇到过trait,比如 laravel 的auth,路由中间件,在一个class中非常耀眼,居然在class中用use,用归用,恐怕自己也很少写。trait,是PHP 5.4.0 引入的概念,既像类,又像接口。性状到底是类还是接口呢?哪个都不是。

性状是类的部分实现(即常量,属性和方法),可以混入一个或多个现有的PHP类中(性状不能单独 实例化 ,还必须得靠其他类使用)。性状有两个作用:表明类可以做什么(像是接口);提供模块化实现(像是类)。

为什么使用性状?

一句话概括:类实现”多继承”,为啥要引号来表示这个多继承呢?PHP本来就是单继承,性状这个多继承只是用法感觉像,实际没有多继承哟!很简单的例子:定义一个Persion类,然后我们的Man类或者Woman类都继承Persion,为啥这样继承,因为他们都属于Persion类,不管你是男人还是女人都是人,没毛病吧,这是我们经典的面向对象,java,php等面向对象的语言大家都能理解。现在有一个类叫FacePainting(化妆),这个类只有Woman才用,Man不用(人妖,伪娘请滚开,你不属于Man),那么问题来了,Woman已经继承了Persion,如果把FacePainting类取消,放入到Persion不合适吧,而且FacePainting(化妆)这个类还可能在其他类中也使用,比如Cosplay这个类也要用到FacePainting(化妆),哈哈哈,很好理解了吧,把FacePainting(化妆)定义成性状,就可以为我们解决了这个问题,当Woman类和Cosplay类都使用FacePainting(trait),那么Woman类和Cosplay类都拥有了FacePainting(trait)里面的方法了。

如何创建性状?

关键字: trait

先来回想我们如何写一个类:

class Test {

// 属性

// 方法

}

其实当你写性状的时候就和写类一样的,只是把class关键字变成trait关键字

trait Test {

// 属性

// 方法

}

非常简单吧,而且性状(trait)也可以使用命名空间,也能psr-4自动加载,所以,我的理解就是一个被弱化的class, 而且这个弱化的class还不能直接实例化,哈哈哈哈,对,trait是不能实例化的(不能new)!

官方原文(其实很好理解):

Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。

Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。

如何使用性状?

我们知道了trait是不能被实例化的,那么就很容易理解,为啥在一个类里面使用use来使用trait

class Test {

use Test; // 使用Test这个trait 非常简单吧

// 属性

// 方法

}

有些class里面没有一个方法,只有一个use Trait; 但是实例化后又很多方法可以用,小伙伴们现在知道为啥了吗?对,方法都在这个trait中,但是也有可能在这个class继承的父类中哟,反正现在IDE都能帮你直接定位到,哈哈哈,我估摸着忙着做业务逻辑(早下班,好约会)都没注意看到底是父类的方法还是trait的方法。

来几个官方例子,加深下理解(这个东西确实不难,看看就能理解了):

Example #1 Trait 示例

 <?php
trait ezcReflectionReturnInfo {
    function getReturnType() { /*1*/ }
    function getReturnDescription() { /*2*/ }
}

class ezcReflectionMethod extends ReflectionMethod {
    use ezcReflectionReturnInfo;
    /* ... */}

class ezcReflectionFunction extends ReflectionFunction {
    use ezcReflectionReturnInfo;
    /* ... */}
?>  

Example #2 优先顺序示例

从基类继承的成员被插入的 SayWorld Trait 中的 My HelloWorld 方法所覆盖。其行为 MyHelloWorld 类中定义的方法一致。优先顺序是当前类中的方法会覆盖 trait 方法,而 trait 方法又覆盖了基类中的方法。

 <?php
class Base {
    public function sayHello() {
        echo 'Hello ';
    }
}

trait SayWorld {
    public function sayHello() {
        parent::sayHello();
        echo 'World!';
    }
}

class MyHelloWorld extends Base {
    use SayWorld;
}

$o = new MyHelloWorld();
$o->sayHello();
?>  

结果是:

Hello World!

Example #3 另一个优先级顺序的例子

 <?php
trait HelloWorld {
    public function sayHello() {
        echo 'Hello World!';
    }
}

class TheWorldIsNotEnough {
    use HelloWorld;
    public function sayHello() {
        echo 'Hello Universe!';
    }
}

$o = new TheWorldIsNotEnough();
$o->sayHello();
?>  

结果是:

Hello Universe!

Example #4 多个 trait 的用法

通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中。

 <?php
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();
?>  

结果是:

Hello World!

以上基本就是我们trait常用的基础知识,还有更多的比如:如果两个 trait 都插入了一个同名的方法,一个class用了这两个trait,需要如何解决冲突?如何修改trait的方法访问控制?还有很多问题大家可以直接去php官方手册查看,我反正看了都会忘,因为这个东西确实用的少,更别说那些问题了,哈哈哈哈,比较懒,了解这些基础的知识点,基本足够你在项目中使用了,但是你会用吗?很多人情愿定义一个类,多实例化一个类,也难得用trait吧,这也是为啥我们实际使用中trait用的那么少的原因,如果你是追求高质量代码的phper,那么trait绝对会帮助你,普通玩家还是赶紧写个class,直接new了开始用吧,早写完,早下班,好和妹子吃饭呢,哈哈哈哈。

附上trait官方链接供高玩食用:

后续会继续更新,感兴趣的小伙伴可以收藏下哟!

欢迎有问题或者项目开发有问题的小伙伴(妹子优先)添加微信:wxmm686800,共同成长!不好意思可以邮箱联系:lirui310@aliyun.com

文章来源:智云一二三科技

文章标题:我们身边的现代PHP(二)

文章地址:https://www.zhihuclub.com/78414.shtml

关于作者: 智云科技

热门文章

网站地图