method_exists VS is_callable

简介: 今天看到一篇介绍,关于 method_exist 的,我觉得自己也有必要记录一下。 在很多应用中,我们经常能够看到下面的这种用法。用来检查一个对象的一个方法是否存在: if (method_exists($object, 'SomeMethod')) {      $object->SomeMethod($this, TRUE); } 这段代码的目的非常容易理解,有一个对象为 $object,我们想知道他是否有一个方法为 SomeMethod 。

今天看到一篇介绍,关于 method_exist 的,我觉得自己也有必要记录一下。


在很多应用中,我们经常能够看到下面的这种用法。用来检查一个对象的一个方法是否存在:


if  ( method_exists ( $object ,   ' SomeMethod ' )) {   
   
$object -> SomeMethod( $this ,   TRUE ); 
}


这段代码的目的非常容易理解,有一个对象为 $object,我们想知道他是否有一个方法为 SomeMethod 。如果有,就调用这个方法。


这个代码看起来很正确,而且在大部分的时候,工作的也非常好。但是如果这个 $object 对象的方法对于当前的运行环境是不可见的,程序还能正常运行吗?method_exists 正如这个函数名一样,只是对我们提供的类或对象检查是否有我们所期望的方法,如果有,就返回TRUE,如果没有,就返回FALSE,这里并没有考虑可见性的问题。所以,如果你恰好判断一个私有或者受保护的方法时,你能够得到一个正确的返回,但是执行的时候,会得到一个 “Fatal Error”。


正确的做法


其实上面一段代码的真正意图应该理解为:对于提供的类或者对象,我们能否在当前的作用域中调用他的 SomeMethod 方法。而这正是 is_callable() 存在的目的。


如何来做


is_callable 接收一个回调参数,可以指定一个函数名称或者一个包含方法名和对象的数组,如果在当前作用域中可以执行,就返回TRUE,如果不能就FALSE。


if  ( is_callable ( array ( $object ,   ' SomeMethod ' ))) {
   
$object -> SomeMethod( $this ,   TRUE ); 
}


下面是一个例子,用来说明 method_exists 和 is_callable 的区别:



class  Foo {
    
public   function  PublicMethod(){}
    
private   function  PrivateMethod(){}
    
public   static   function  PublicStaticMethod(){}
    
private   static   function  PrivateStaticMethod(){}
}

$foo   =   new  Foo();

$callbacks   =   array (
    
array ( $foo ,   ' PublicMethod ' ) ,
    
array ( $foo ,   ' PrivateMethod ' ) ,
    
array ( $foo ,   ' PublicStaticMethod ' ) ,
    
array ( $foo ,   ' PrivateStaticMethod ' ) ,
    
array ( ' Foo ' ,   ' PublicMethod ' ) ,
    
array ( ' Foo ' ,   ' PrivateMethod ' ) ,
    
array ( ' Foo ' ,   ' PublicStaticMethod ' ) ,
    
array ( ' Foo ' ,   ' PrivateStaticMethod ' ) ,
);

foreach  ( $callbacks   as   $callback ){
    
var_dump ( $callback );
    
var_dump ( method_exists ( $callback [ 0 ] ,   $callback [ 1 ]));
    
var_dump ( is_callable ( $callback ));
    
echo   str_repeat ( ' - ' ,   40 );
    
echo   ' <br /> ' ;
}


执行这个例子,我们就能购清晰的看到两个函数间的差别。


补充


is_callable 还有其他的用法,例如不检查所提供的类或方法,只是检查函数或方法的语法是否正确。像 method_exists一样,is_callable 可以触发类的自动加载。


如果一个对象有魔术方法 __call,在进行方法判断的时候 method_exists 会返回FALSE , 而is_callable 会返回TRUE。


如下例:


class  MethodTest {
    
public   function  __call( $name ,   $arguments ){
        
echo   ' Calling object method  '   .   $name   .   '   '   .   implode ( ' ' ,   $arguments );
        
echo   ' <br /> ' ;
    }
}

$obj   =   new  MethodTest();

$obj -> runtest( ' in object context ' );
var_dump ( method_exists ( $obj , ' runtest ' ));
var_dump ( is_callable ( array ( $obj , ' runtest ' )));
echo   ' <br /> ' ;


参考资料:

1、is_callable

2、method_exists

相关文章
|
2月前
|
存储 Java
高并发编程之多线程锁和Callable&Future 接口
高并发编程之多线程锁和Callable&Future 接口
54 1
|
2月前
|
Java
Java并发编程:理解并使用Future和Callable接口
【2月更文挑战第25天】 在Java中,多线程编程是一个重要的概念,它允许我们同时执行多个任务。然而,有时候我们需要等待一个或多个线程完成,然后才能继续执行其他任务。这就需要使用到Future和Callable接口。本文将深入探讨这两个接口的用法,以及它们如何帮助我们更好地管理多线程。
|
8月前
|
Java
ExecutorService、Callable、Future实现有返回结果的多线程原理解析
ExecutorService、Callable、Future实现有返回结果的多线程原理解析
56 0
|
8月前
|
存储 Java
并发编程系列教程(09) - Callable与Future模式
并发编程系列教程(09) - Callable与Future模式
34 0
|
11月前
|
Java
【并发技术11】Callable与Future的应用
【并发技术11】Callable与Future的应用
|
Java Android开发
Android中Callable、Future、FutureTask的概念以及几种线程池的使用
在开始介绍线程池之前,先来介绍下`Callable`和`Future`的概念,众所周知,`Android`中实现多线程的方式有两种,实现`Runnable`接口或者继承一个`Thread`,但是这两种方式都有一个缺点:在任务执行完成之后没有返回结果,所以在`Java 1.5`之后,出现了`Callable`和`Future`,通过他们构建的线程,可以在线程执行完成之后得到返回结果。
241 0
|
存储 Java
高并发编程之多线程锁和Callable&Future 接口
5 多线程锁 5.1 锁的八个问题演示 package com.xingchen.sync; import java.util.concurrent.TimeUnit; class Phone { public static synchronized void sendSMS() throws Exception { //停留4秒 TimeUnit.SECONDS.sleep(4); System.out.println("------sendSMS"); } public synchronized void
99 0
|
Java
Future和Callable学习
通常使用线程池+Runnable的时候,会发现Runnable不能返回值,也就执行的结果情况,同时对于出现异常,我们获取异常信息,进行相应的处理。如果需要返回结果,同时需要进一步加工的时候,就可以考虑使用Future+Callable了。同时接口Future的默认实现是FutureTask,因此对于其实现get()方法,会有一个问题,就是如果前面的任务一旦执行的时间耗时较长的时候,就会出现一直阻塞的状态,此时就会出现排队等待的状态,大大影响其性能。适用场景:当一个线程需要等待另一个线程把某个任务执行完成后它才能继续执行,此时可以使用FutureTask。因为FutureTask基于AQS实现,
81 0
Future和Callable学习