什么是php的性状(Trait)

很多PHP开发朋友都没有弄清楚Trait(性状)。这是PHP5.4.0引入的新概念,既像类又像接口。性状是类的补分实现(即常量、属性、方法),可以混入一个或者多个现有的PHP类中。 性状有两个作用:表明类可以做什么(像是接口);提供模块化实现(像是类)。
PHP使用一种典型的继承模型,在这种模型中,我们先编写一个通用的根类,实现基本功能,然后扩展这个根类,创建更具体的类,从直接父类继承实现。这叫继承层次结构,很多编程语言都使用了这个模式
大多时候,这种典型的继承模型能良好的运行,可是,如果想让两个无关的PHP类具有类似的行为,应该怎么做呢?

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

创建一个父类让Shop和Car都继承它
创建一个接口,定义实现地理编码功能需要哪些方法,然后让Shop和Car两个类都实现这个接口
创建一个性状,定义并实现地理编码相关的方法,然后把在Shop和Car两个类中混入这个性状
第一种解决方法不好,因为我们强制让两个无关的类继承同一个祖先,而很明显,这个祖先不属于各自的继承层次结构。

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

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

如何创建性状?

trait Geocodable 
{
    // 这里是性状的实现
}

如何使用性状?

class Shop
{
    use Geocodable;

    // 这里是类的实现
}

例子
创建一个Geocodable 性状

trait Geocodable 
{

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

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

    /** 
    * 处理后结果对象
    * @var \Geocoder\Result\Geocoded 
    */
    protected $geocoderResult;

    //注入Geocoder对象
    public function setGeocoder(\Geocoder\GeocoderInterface $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 \Geocoder\HttpAdapter\CurlHttpAdapter();
$geocoderAdapter = new \Geocoder\Provider\GoogleMapsProvider($geocoderAdapter);
$geocoder = new \Geocoder\Geocoder($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;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值