对象接口
使用接口(interface),可以指定某个类必须实现哪些方法和属性,但不需要定义这些方法或属性的具体内容。
由于接口(interface)和类(class)、trait 共享了命名空间,所以它们不能重名。
接口就像定义一个标准的类一样,通过 interface 关键字替换掉
class 关键字来定义,但其中所有的方法都是空的。
接口中定义的所有方法都必须是 public ,这是接口的特性。
在实践中,往往出于两个辅助目的使用接口:
因为实现了同一个接口,所以开发者创建的对象虽然源自不同的类,但可能可以交换使用。
常用于多个数据库的服务访问、多个支付网关、不同的缓存策略等。
可能不需要任何代码修改,就能切换不同的实现方式。
能够让函数与方法接受一个符合接口的参数,而不需要关心对象如何做、如何实现。
这些接口常常命名成类似 Iterable、Cacheable、Renderable,
以便于体现出功能的含义。
接口可以定义魔术方法,以便要求类(class)实现这些方法。
注意:
虽然没有禁止,但是强烈建议不要在接口中使用 构造器。
因为这样在对象实现接口时,会大幅降低灵活性。
此外,也不能强制确保构造器遵守继承规则,将导致不可预料的行为结果。
实现(implements)
要实现一个接口,使用 implements
操作符。类中必须实现接口中定义的所有方法,否则会报一个致命错误。
类可以实现多个接口,用逗号来分隔多个接口的名称。
警告
实现接口的时候,class 中的参数名称不必和接口完全一致。
然而, PHP 8.0 起语法开始支持命名参数,
也就是说调用方会依赖接口中参数的名称。
因此,强烈建议开发者的参数的命名,在类和接口中保持一致。
注意:
接口也可以通过 extends 操作符扩展。
注意:
类实现接口时,必须以兼容的签名定义接口中所有方法。类可以实现多个声明了相同方法名称的接口。在这种情况下,实现必须遵循所有接口的签名兼容性规则。因此可以应用协变和逆变。
常量
接口中也可以定义常量。接口常量和类常量的使用完全相同, 在 PHP 8.1.0 之前
不能被子类或子接口所覆盖。
属性
自 PHP 8.4.0 起,接口也可以声明属性。如果声明了属性,则必须指定属性是可读、可写还是可读可写。接口声明仅适用于 public 读写访问。
类可以通过多种方式满足接口属性。可以定义 public 属性。可以定义仅实现相应挂钩的 public 虚拟属性。或者属性读取可以由 readonly
属性满足。但是可 set 的接口属性可能不是 readonly。
示例 #1 接口属性示例
strtoupper($this->writeable); } // 该接口仅要求属性可 set, // 但包含 get 操作也是完全有效的。 // 此示例创建了虚拟属性,这很好。 public string $writeable { get => $this->written; set { $this->written = $value; } } // 此属性要求读取和写入均可, // 因此需要实现两者,或者允许它具有默认行为。 public string $both { get => $this->all; set { $this->all = strtoupper($value); } }}?>
示例
示例 #2 接口示例
vars[$name] = $var; } public function getHtml($template) { foreach($this->vars as $name => $value) { $template = str_replace('{' . $name . '}', $value, $template); } return $template; }}// 下面的写法是错误的,会报错,因为没有实现 getHtml():// Fatal error: Class BadTemplate contains 1 abstract methods// and must therefore be declared abstract (Template::getHtml)class BadTemplate implements Template{ private $vars = []; public function setVariable($name, $var) { $this->vars[$name] = $var; }}?>
示例 #3 可扩充的接口
示例 #4 多接口的差异兼容性
示例 #5 扩展多个接口
示例 #6 使用接口常量
示例 #7 抽象(abstract)类的接口使用
示例 #8 同时使用扩展和实现
接口加上类型约束,提供了一种很好的方式来确保某个对象包含有某些方法。参见
instanceof 操作符和类型声明。