(三)PHP面向对象理论3---接口与反射

一. 接口:
1.采用一个特定接口的所有代码都知道对于那个接口会调用什么方法。接口除了可以包含方法外还能包含常量。
2.接口为抽象而生。
<?php
header("Content-type: text/html; charset=utf-8");
interface mobile{
    public function run();
}

class plain implements mobile{
    public function run(){
        echo "我是灰机我是灰机";
    }

    public function fly(){
        echo "飞呀飞";
    }
}

class car implements mobile{
    public function run(){
        echo "我是汽车我是汽车\r\n";
    }
}

class machine{
    function demo(mobile $a){
        $a->fly();
    }
}

$obj = new machine();
$obj->demo(new plain());
$obj->demo(new car());
3.PHP的接口可以淡化为设计文档:
4.补充:PHP5对面向对象的特性做了增强,其中有SPL(标准PHP库)。SPL中能实现很多接口,其中最主要的是Interator接口。
<?php
$dir = new DirectoryIterator(dirname(__FILE__));
foreach ($dir as $fileinfo){
    if (!$fileinfo -> isDir()){
        echo $fileinfo->getFilename(),'\t',$fileinfo->getSize(),PHP_EOL;
    }
}
5.traits被视为加强型的接口:
<?php
trait Hello{
    public function sayHello(){
        echo 'Hello';
    }
}

trait World{
    public function sayWorld(){
        echo 'World';
    }
}

class MyHelloWorld{
    use Hello,World;
    public function sayExclamationMark(){
        echo "!";
    }
}

$o = new MyHelloWorld();
$o ->sayHello();
$o ->sayWorld();
$o->sayExclamationMark();
?>
7.总结:
a.接口作为一种规范和契约的存在。做为规范,接口应该保证可用性;做为契约,接口应该保证可控性。
b.接口只是一个声明,使用了interface关键字就应该实现它
c.PHP中的接口存在两个不足,一是没有契约限制,二是缺少足够多的内部接口
二.反射:
1.反射是在PHP运行状态中,扩展分析PHP程序,导出或者提取出关于类、方法、属性、参数等的详细信息,包括注释。这种动态获取信息以及动态调用对象方法的功能称为反射API。
<?php
header("Content-type: text/html; charset=utf-8");

class person{
    public $name;
    public $gender;
    public function say(){
        echo $this->name,"\tis ",$this->gender,"\r\n";
    }

    public function __set($name,$value){
        echo "Setting $name to $value \r\n";
        $this->$name = $value;
    }

    public function __get($name){
        if (!isset($this->$name)){
            echo "未设置";
            $this->$name = "正在为你设置默认值";
        }
        return $this->name;
    }
}

$student = new person();
$student->name = 'Tom';
$student->gender = 'male';
$student->age = 24;

$reflect = new ReflectionObject($student);
$props = $reflect->getProperties();
foreach ($props as $prop){
    print $prop->getName()."\n";
}

$m=$reflect->getMethods();
foreach($m as $prop){
    print $prop->getName()."\n";
}

//使用class返回对象属性的关联数组以及更多的信息
var_dump(get_object_vars($student));
var_dump(get_class_vars(get_class($student)));
var_dump(get_class_methods(get_class($student)));
echo get_class($student);
2.使用反射API
<?php
//此代码无结果。
//实验反射类
$obj = new ReflectionClass('person');
$className = $obj->getName();
$Methods = $Properties = array();
foreach($obj ->getProperties() as $v){
    $Properties[ $v->getName() ] = $v;
}

foreach($obj->getMethods() as $v){
    $Methods[$v->getName()] = $v;
}

echo "class {$className} \n{\n";
is_array($Properties) && ksort($Properties);

foreach($Properties as $k=>$v){
    echo "\t";
    echo $v->isPublic() ? 'public' : '',$v->isPrivate() ? 'private' : '',
    $v->isProtected() ? 'protected' : '',
    $v->isStatic() ? 'static' : '';
    echo "\t{$k}\n";
}

echo "\n";
if (is_array($Methods)) ksort($Methods);
foreach ($Methods as $k=>$v){
    echo "\tfunction {$k}(){} \n";
}
echo "}\n";
3.反射的作用:
反射可以用于文档生成。因此可以用它对文件里的类进行扫描,逐个生成描述文档。
<?php
header("Content-type: text/html; charset=utf-8");

class mysql{
    function connect($db){
        echo "连接到数据库{db[0]}\r\n";
    }
}

class sqlproxy{
    private $target;
    function __construct($tar){
        $this->target[] = new $tar();
    }

    function __call($name,$args){
        foreach ($this->target as $obj){
            $r = new ReflectionClass($obj);
            if ($method = $r->getMethod($name)){
                if ($method ->isPublic() && !$method->isAbstract()){
                    echo "方法前拦截记录 LOG\r\n";
                    $method->invoke($obj,$args);
                    echo "方法后拦截\r\n";
                }
            }
        }
    }
}

$obj = new sqlproxy('mysql');
$obj->connect('member');
4.反射的用途:
a.对对象进行高度
b.获取类的信息
5.反射的优缺点:
反射能保持代码的优雅和简洁,但反射也会破坏类的封装性。

你可能感兴趣的:(PHP,继承,面向对象,反射,阿里云)