面向接口编程
接口定义一套规范,描述一个“物”的功能,要求如果现实中的“物”想成为可用,就必须实现这些基本功能。
接口本身并不提供实现,只是提供一个规范。如果我们知道一个类实现了某个接口,那么就知道了可以调用该接口的哪些方法,我们只需要知道这些就够了。
由于PHP是弱类型,且强调灵活,所以并不推荐大规模使用接口,而是仅在部分“内核”代码中使用接口,因为PHP中的接口已经失去很多接口应该具有的语义。从语义上考虑,可以更多地使用抽象类。至于抽象类和接口的比较,不再赘述。
接口作为一种规范和契约存在。作为规范,接口应该保证可用性;作为契约,接口应该保证可控性。
PHP中的接口存在两个不足,一是没有契约限制,二是缺少足够多的内部接口。
一个子类如果implements一个接口,就必须实现接口中的所有方法(不管是否需要);如果继承一个抽象类,只需要实现需要的方法即可
如果一个接口中定义的方法名改变了,那么所有实现此接口的子类需要同步更新方法名;而抽象类中如果方法名改变了,其子类对应的方法名将不受影响,只是变成了一个新的方法而已
抽象类只能单继承,当一个子类需要实现的功能需要继承多个父类时,就必须使用接口
interface Demo
{
public function func1();
public function func2();
}
interface Demo2 extends Demo
{
public function func3();
public function func4();
}
interface Demo3
{
public function func5();
public function func6();
}
class ParentClass
{
public function func7(){}
}
class ChildClass extends ParentClass implements Demo2, Demo3
{
public function func1(){}
public function func2(){}
public function func3(){}
public function func4(){}
public function func5(){}
public function func6(){}
}
反射
面向对象编程中对象被赋予了自省的能力,而这个自省的过程就是反射。
反射,直观理解就是根据到达地找到出发地和来源。
$ref = new ReflectionClass($classname)
$ref->getProperties();
$ref->getMethods();
$ref->isInstantiable();
$res->newInstanceArgs();
在平常开发中,用到反射的地方不多:一个是对对象进行调试,另一个是获取类的信息。在MVC和插件开发中,使用反射很常见,但是反射的消耗也很大,在可以找到替代方案的情况下,就不要滥用。
很多时候,善用反射能保持代码的优雅和简洁,但反射也会破坏类的封装性,因为反射可以使本不应该暴露的方法或属性被强制暴露了出来,这既是优点也是缺点。
<?php
// 厨师
class Cook
{
public function meal()
{
echo 'meal <br>';
}
public function drink()
{
echo 'drink <br>';
}
public function ok()
{
echo 'ok <br>';
}
}
// 命令接口
interface Command
{
public function execute();
}
// 炒菜命令
class MealCommand implements Command
{
public $cook;
public function __construct($cook){
$this->cook = $cook;
}
public function execute()
{
$this->cook->meal();
}
}
// 饮料命令
class DrinkCommand implements Command
{
public $cook;
public function __construct($cook)
{
$this->cook = $cook;
}
public function execute()
{
$this->cook->drink();
}
}
// 顾客下单
class cookController
{
public $mealCommand;
public $drinkCommand;
public function __construct(MealCommand $mealCommand, DrinkCommand $drinkCommand)
{
$this->mealCommand = $mealCommand;
$this->drinkCommand = $drinkCommand;
}
public function callMeal()
{
$this->mealCommand->execute();
}
public function callDrink()
{
$this->drinkCommand->execute();
}
}
$cook = new Cook();
$mealCommand = new MealCommand($cook);
$drinkCommand = new DrinkCommand($cook);
$c = new cookController($mealCommand, $drinkCommand);
$c->callMeal();
$c->callDrink();