资讯专栏INFORMATION COLUMN

【modernPHP专题(9)】匿名类

ninefive / 677人阅读

摘要:复制当前闭包对象,绑定指定的对象和类作用域。类作用域,可以是对象,也可以是实例名称什么是匿名类先理解以下三个例子例闭包函数都是继承类返回匿名函数返回匿名函数,也就是闭包函数,所有闭包函数都是继承类输出例将一个匿名函数绑定到一个类中。

类结构
Closure {
    /* 方法 */
    // 用于禁止实例化的构造函数
    __construct ( void )
    
    // 复制一个闭包,绑定指定的$this对象和类作用域。
    public static Closure bind ( Closure $closure , object $newthis [, mixed $newscope = "static" ] )
   
    // 复制当前闭包对象,绑定指定的$this对象和类作用域。
    public Closure bindTo ( object $newthis [, mixed $newscope = "static" ] )
}

// 类作用域,可以是对象,也可以是实例名称
什么是匿名类?

先理解以下三个例子

例1. 闭包函数都是继承Closure类
class A {
    public static function testA() {
        return function($i) { //返回匿名函数
            return $i+100;
        };
    }
}

function B(Closure $callback)
{
    return $callback(200);
}
$a = B(A::testA());

// A::testA() 返回匿名函数,也就是闭包函数,所有闭包函数都是继承Closure类
// print_r($a); //输出 300
例2. 将一个匿名函数绑定到一个类中。返回Closure类
class A {
    public $base = 100;
    public function funca()
    {
        echo 2222;
    }
}

class B {
    private $base = 1000;
}

// bind : 复制一个闭包,绑定指定的$this对象和类作用域。
$f = function () {
    return $this->base + 3;
};

print_r($f);
/**
 * $f其实就是一个closure对象
 Closure Object
    (
    )
 */

$a = Closure::bind($f, new A);
print_r($a());//out: 103
print_r($a);
/*
 * out:
    Closure Object
    (
        [this] => A Object
            (
                [base] => 100
            )

    )
 */

// 第三个参数就声明了这个函数的可调用范围(如果该函数要调用private)
, 该参数可以是对象实例,也可以是类名
$b = Closure::bind($f, new B, "B");

print_r($b);
/**
 * out:
Closure Object
    (
    [this] => B Object
        (
            [base:B:private] => 1000
        )
)
 */
print_r($b());//out: 1003
3. 第二参数为null,代表静态调用static
class A {
    private static $sfoo = 1;
    private $ifoo = 2;
}

// 要调静态的属性,就必须声明static
$cl1 = static function() {
    return A::$sfoo;
};
$cl2 = function() {
    return $this->ifoo;
};

// 第二参数为null,就代表调用static
$bcl1 = Closure::bind($cl1, null, "A");
$bcl2 = Closure::bind($cl2, new A(), "A");

// 以closure对象调用静态属性
$bcl3 = $cl1->bindTo(null,"A");

echo $bcl1(), "
";//输出 1
echo $bcl2(), "
";//输出 2
echo $bcl3(); // 输出1
匿名类有什么用? 给类动态添加新方法
trait DynamicTrait {
    /**
     * 自动调用类中存在的方法
     */
    public function __call($name, $args) {
        if(is_callable($this->$name)){
            return call_user_func($this->$name, $args);
        }else{
            throw new RuntimeException("Method {$name} does not exist");
        }
    }
    /**
     * 添加方法
     */
    public function __set($name, $value) {
        $this->$name = is_callable($value)?
            $value->bindTo($this, $this):
            $value;
    }
}
/**
 * 只带属性不带方法动物类
 *
 * @author fantasy
 */
class Animal {
    use DynamicTrait;
    private $dog = "汪汪队";
}
$animal = new Animal;

// 往动物类实例中添加一个方法获取实例的私有属性$dog
$animal->getdog = function() {
    return $this->dog;
};
echo $animal->getdog();//输出 汪汪队
模板渲染输出

Template.php

class Template{
    /**
     * 渲染方法
     *
     * @access public
     * @param obj 信息类
     * @param string 模板文件名
     */
    public function render($context, $tpl){
        $closure = function($tpl){
            ob_start();
            include $tpl;
            return ob_end_flush();
        };
         
        // PHP7: $closure->call($context, $tpl);
        $closure = $closure->bindTo($context, $context);
        $closure($tpl);
    }
}

Article.php

/**
 * 文章信息类
 */
class Article
{
    private $title = "这是文章标题";
    private $content = "这是文章内容";
}

tpl.php

···
···

title;?>

content;?>

··· ···

index.php

function __autoload($class) {
    require_once "$class.php";
}
$template = new Template;

$template->render(new Article, "tpl.php");
PHP7 新增的call方法
class Value
{
    protected $value;

    public function __construct($value)
    {
        $this->value = $value;
    }

    public function getValue()
    {
        return $this->value;
    }
}

$three = new Value(3);
$four = new Value(4);

$closure = function ($delta){
    return $this->getValue() + $delta;
};

/**
 * function call ($newThis, ...$parameters)
 * 把$closure绑定到$three,并调用;第二参数起就是闭包的参数
 */
echo $closure->call($three , 3);
echo PHP_EOL;
echo $closure->call($four , 4);

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/31424.html

相关文章

  • modernPHP专题(8)】匿名函数和闭包

    摘要:匿名函数输出可以直接将匿名函数进行传递。报错,找不到变量之所以称为副本,是因为通过闭包传值到匿名函数内的变量值也是不能改变。该方法使用了一个作为回调函数。 匿名函数 // Example1 $func = function( $param ) { echo $param; }; $func( some string );//输出:some string // Example2...

    junnplus 评论0 收藏0
  • modernPHP专题(1)】php7常用特性整理

    摘要:它使得在生产环境中启用断言为零成本,并且提供当断言失败时抛出特定异常的能力。错误和异常改变了大多数错误的报告方式。不同于传统的错误报告机制,现在大多数错误被作为异常抛出。 PHP7性能 7最大的亮点,应该就是性能提高了两倍,某些测试环境下甚至提高到三到五倍,具体可以了解以下链接: PHP7 VS HHVM (WordPress) HHVM vs PHP 7 – The Competit...

    Render 评论0 收藏0
  • modernPHP专题(6)】的延迟绑定(后期绑定)

    摘要:实例化对象里面的所在哪个类就返回哪个类。访问的是当前类有点像因为其是继承了的方法,而调用的。由此可见,他们的区别只有在继承中才能体现出来,如果没有任何继承,那么这两者是没有区别的。但如果是在静态方法内本类的话,最好还是用 以static::来调用,是在运行的那个时刻才执行绑定操作; 父类中有个方法是延迟绑定的,在子类::调用这个方法的时候它又回到调用的子类开始向上找; exampl...

    adam1q84 评论0 收藏0
  • modernPHP专题(7)】生成器语法

    摘要:通过生成器来生成关联数组下面每一行是用分号分割的字段组合,第一个字段将被用作键名。正常来说,产生的是一个,它的成员变量与函数不存在别名引用关系。关键字在的版本,生成器允许从其他生成器,可迭代对象或数组通过关键字来生成对应的值输出 一般你在迭代一组数据的时候,需要创建一个数据,假设数组很大,则会消耗很大性能,甚至造成内存不足。 //Fatal error: Allowed memory ...

    jackwang 评论0 收藏0
  • modernPHP专题(12)】魔术方法小结

    说明 魔术方法就是在特定场景下不需要调用而自动执行的方法。因为有魔术方法,所以我们的类可以写得很灵活~ __construct #构造方法,在类被实例化时自动调用,一般用于初始化操作; __destruct #析构方法,对象被销毁时自动调用; __clone() #克隆方法,当对象被克隆时,将会自动调用 __get($key) #属性获取...

    hearaway 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<