资讯专栏INFORMATION COLUMN

什么是Trait(性状)?

sushi / 3267人阅读

摘要:很多开发朋友都没有弄清楚性状。性状有两个作用表明类可以做什么像是接口提供模块化实现像是类。注是不要自我重复的简称,表示不要在多个地方重复编写相同的代码,如果需要修改遵守这个原则编写的代码,只需要在一出修改,改动就能体现到其他地方。

很多PHP开发朋友都没有弄清楚Trait(性状)。这是PHP5.4.0引入的新概念,既像又像接口
性状补分实现(即常量、属性、方法),可以混入一个或者多个现有的PHP类中。
性状有两个作用:表明类可以做什么(像是接口);提供模块化实现(像是类)。

PHP使用一种典型的继承模型,在这种模型中,我们先编写一个通用的根类,实现基本功能,然后扩展这个根类,创建更具体的类,从直接父类继承实现。这叫继承层次结构,很多编程语言都使用了这个模式
大多时候,这种典型的继承模型能良好的运行,可是,如果想让两个无关的PHP类具有类似的行为,应该怎么做呢?

假如ShopCar两个PHP类的作用十分不同,而且在继承层次结构中没有共同的父类。 那么这两个类都应该能使用地理编码技术转化成经纬度,然后在地图上显示。要怎么解决这个问题呢?

创建一个父类ShopCar都继承它

创建一个接口,定义实现地理编码功能需要哪些方法,然后让ShopCar两个类都实现这个接口

创建一个性状,定义并实现地理编码相关的方法,然后把在ShopCar两个类中混入这个性状

第一种解决方法不好,因为我们强制让两个无关的类继承同一个祖先,而很明显,这个祖先不属于各自的继承层次结构。

第二种解决方法好,因为每个类都能保有自然的继承层次结构。但是,我们要在两个类中重复实现的地理编码功能,这不符合DRY原则
DRYDon"t Repeat Yourself(不要自我重复)的简称,表示不要在多个地方重复编写相同的代码,如果需要修改遵守这个原则编写的代码,只需要在一出修改,改动就能体现到其他地方。

第三种解决方法最好,这么做不会搅乱这两个类原本自然的继承层次结构。


如何创建性状?
trait Geocodable 
{
    // 这里是性状的实现
}
如何使用性状?
class Shop
{
    use Geocodable;

    // 这里是类的实现
}

例子

创建一个Geocodable 性状

trait Geocodable 
{

    /**
    * 地址    
    * @var string 
    */
    protected $address;

    /**
    * 编码器对象
    * @var GeocoderGeocoder 
    */
    protected $geocoder;

    /** 
    * 处理后结果对象
    * @var GeocoderResultGeocoded 
    */
    protected $geocoderResult;

    //注入Geocoder对象
    public function setGeocoder(GeocoderGeocoderInterface $geocoder)
    {
        $this->geocoder = $geocoder;
    }

    //设定地址
    public function setAddress($address)
    {
        $this->address = $address;
    }

    //返回纬度
    public function getLatitude()
    {
        if (isset($this->geocoderResult) === false) {
            $this->geocodeAddress();
        }

        return $this->geocoderResult->getLatitude();
    }

    //返回经度
    public function getLongitude()
    {
        if (isset($this->geocoderResult) === false) {
            $this->geocodeAddress();
        }

        return $this->geocoderResult->getLongitude();
    }
    
    //把地址字符串传给Geocoder实例,获取经地理编码器处理得到的结果
    protected function geocodeAddress()
    {
        $this->geocoderResult = $this->geocoder->geocode($this->address);

        return true;
    }
}

使用性状

$geocoderAdapter = new GeocoderHttpAdapterCurlHttpAdapter();
$geocoderAdapter = new GeocoderProviderGoogleMapsProvider($geocoderAdapter);
$geocoder = new GeocoderGeocoder($geocoderProvider);

$store = new Shop();
$store->setAddress("420 9th Avenue, New York, NY 10001 USA");
$store->setGeocoder($geocoder);

$latiude   = $store->getLatitude();
$longitude = $store->getLongitude();
echo $latitude, ":", $longitude;

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/22101.html

相关文章

  • 如何在 Laravel 中 “规范” 的开发验证码发送功能【社交系统ThinkSNS研发日记十一】

    摘要:需求场景发送验证码或者消息通知,可发送到手机或邮箱中。完成首先,在中的规范就是使用的消息通知,这里基于场景为验证码。所以我们在验证码模型中添加是完全符合通知的正确使用的。 顺便发个小通知:7月15日ThinkSNS+开源版发布,同时非开源的APP也走出内测阶段,体验二维码也全面发布体验。 什么是ThinkSNS ? ThinkSNS(简称TS),一款全平台综合性社交系统,为国内外大中小...

    Flands 评论0 收藏0
  • 深入解析 composer 的自动加载原理

    摘要:从这个例子中,我们可以看出至少要做三件事情根据类名确定类文件名确定类文件所在的磁盘路径将类从磁盘文件中加载到系统中。 深入解析 composer 的自动加载原理 前言 PHP 自5.3的版本之后,已经重焕新生,命名空间、性状(trait)、闭包、接口、PSR 规范、以及 composer 的出现已经让 PHP 变成了一门现代化的脚本语言。PHP 的生态系统也一直在演进,而 compos...

    Darkgel 评论0 收藏0

发表评论

0条评论

sushi

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<