PHP 中的接口 interface

PHP interface

PHP 类是单继承,不支持多继承,当一个类需要多个类的功能时,继承就无能为力了,为此 PHP 引入了类的接口技术。

如果一个抽象类里面的所有方法都是抽象方法,且没有声明变量,而且接口里面所有的成员都是 public 权限的,那么这种特殊的抽象类就叫 接口 。

接口使用关键字 interface 来定义,并使用关键字 implements 来实现接口中的方法,且必须实现该接口的所有方法。

<?php
//定义接口
interface User{
    
    
    function getDiscount();
    function getUserType();
}
//VIP用户 接口实现
class VipUser implements User{
    
    
    // VIP 用户折扣系数
    private $discount = 0.8;
    function getDiscount() {
    
    
        return $this->discount;
    }
    function getUserType() {
    
    
        return "VIP用户";
    }
}
class Goods{
    
    
    var $price = 100;
    var $vc;
    //定义 User 接口类型参数,这时并不知道是什么用户
    function run(User $vc){
    
    
        $this->vc = $vc;
        $discount = $this->vc->getDiscount();
		$usertype = $this->vc->getUserType();
        echo $usertype."商品价格:".$this->price*$discount;
    }
}
$display = new Goods();
$display ->run(new VipUser);
//可以是更多其他用户类型
?>

运行该例子,输出:

VIP用户商品价格:80 元

实现多个接口

PHP也可以在继承一个类的时候同时实现多个接口:

class 子类 extends 父类 implemtns 接口1, 接口2, ...
{
    
    
    ......
}

抽象类和接口的区别

接口是特殊的抽象类(abstract),也可以看做是一个模型的规范。接口与抽象类大致区别如下:

一个子类如果 implements 一个接口,就必须实现接口中的所有方法(不管是否需要);如果是继承一个抽象类,只需要实现需要的方法即可。
如果一个接口中定义的方法名改变了,那么所有实现此接口的子类需要同步更新方法名;而抽象类中如果方法名改变了,其子类对应的方法名将不受影响,只是变成了一个新的方法而已(相对老的方法实现)。
抽象类只能单继承,当一个子类需要实现的功能需要继承自多个父类时,就必须使用接口

原因

开发者使用接口来描述一个或者一组类的共同行为。
为什么只负责封装实现而不负责处理每个类的详细信息?
这是为了解耦,接口允许你在不更改详细信息的情况下更改实现,也就是你使用此实现的方式。

Symfony 示例

对于 Symfony 而言,如果你想要实现任何缓存系统,最佳实践就是按照下面的方式来做

use Symfony\Contracts\Cache\CacheInterface;

class MyClass {
    
    
    private $cache;
    public function __construct(CacheInterface $cache)
    {
    
    
        $this->cache = $cache;
    }
}

通过依赖注入,将缓存接口注入到我们的类中。下次我们修改缓存系统时,MyClass 类不需要做任何的改变。

总结

PHP 接口是类的方法模板,这对于解耦实现及使用是非常有帮助的。
当你需要保持灵活性并确保所有开发人员都遵循一组规则时,此功能特别有用。

拓展

除了interface和静态类以外我们还可以使用:Trait

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

  • Trait 的用法很简单直接在 类里面 use 即可。

  • 注意:Trait中的方法会覆盖 基类中的同名方法,而本类会覆盖Trait中同名方法。当trait定义了属性后,类就不能定义同样名称的属性,否则会产生 fatal error,除非是设置成相同可见度、相同默认值。

转载自:http://www.5idev.com/p-php_class_interface_implements.shtml

猜你喜欢

转载自blog.csdn.net/qq_39004843/article/details/108165451