在我的验证类中,我传递了不同的类对象,需要在这些类上调用方法。现在的问题是。如何确保该方法存在。
我应该像这样使用instanceof
:
...
...
if($passedObject instanceof MyExpectedClass) {
//then call the rquired method
}
...
...
或者应该像这样method_exists
:
...
...
if(method_exists($passedObject, 'MyExpectedMethod')) {
//then call the rquired method
}
...
...
我很困惑。哪一个更好的方法。
我知道如果传递的Object是期望类的一个实例,那么预期的方法也将存在,因为MyExpected类实现了包含预期方法的接口。希望这将使情景更加清晰。
答案 0 :(得分:1)
这是两种不同的验证,instanceof检查提供的对象是否是特定类的实例,而method_exists检查某个类中是否存在某个方法,因此第一次验证将永远不会告诉您传递的对象是否包含该方法,它只会告诉你它是该方法的一个实例。你应该使用method_exists()
简单测试
class MyClass {
public function myMethod() {
// code
}
}
$obj = new MyClass;
var_dump(method_exists($obj, 'myMethod')); // true
答案 1 :(得分:0)
您可以创建一个界面:
interface ExpectedMethodInterface
{
/**
* My expected method
*
* @return ...expected return type...
*/
public function myExpectedMethod();
}
然后每个具有此方法的类应该实现如下接口:
class MyClassWithExpectedMethod implements ExpectedMethodInterface
{
/**
* My expected method
*
* @return ...expected return type...
*/
public function myExpectedMethod()
{
...body for method...
}
}
然后你可以检查:
if($passedObject instanceof ExpectedMethodInterface)
{
... call your method...
}
如果你使用php
5.4.0或更高版本,你也可以制作一个特性并在你的课程中使用它来防止代码重复:
trait ExpectedMethodTrait
{
/**
* My expected method
*
* @return ...expected return type...
*/
public function myExpectedMethod()
{
...body for method...
}
}
然后使用你的特征:
class MyClassWithExpectedMethod implements ExpectedMethodInterface
{
use ExpectedMethodTrait;
}
答案 2 :(得分:0)
如果您正在寻找最有效的方法,那么instanceOf
会更好,但不会更多。
interface HasMethod {
public function myMethod();
}
class MyClass1 implements HasMethod {
public function myMethod() {}
}
class MyClass2 {
public function myMethod() {}
}
$myClass1 = new MyClass1();
$myClass2 = new MyClass2();
$times = [0,0,0];
$j = 0;
for($i = 0; $i < 100000; ++$i) {
$start = microtime(1);
($myClass1 instanceof HasMethod) && $j++;
$times[0] += microtime(1) - $start;
$start = microtime(1);
(method_exists($myClass1, 'myMethod')) && $j++;
$times[1] += microtime(1) - $start;
$start = microtime(1);
(method_exists($myClass2, 'myMethod')) && $j++;
$times[2] += microtime(1) - $start;
}
print_r($times);
结果:
Array
(
[0] => 0.46121835708618 //instanceOf with interface
[1] => 0.53055930137634 //method_exists with interface
[2] => 0.4961085319519 //method_exists without interface
)
请记住method_exists
可以将结果缓存到所调用的特定类 - Reflection类只检查一次给定的类,无论你创建了多少个Reflection实例 - 这是一个性能问题,因为类实例不会在运行时更改定义,因此反射重复工作中没有任何意义可以产生相同的结果。我不知道这是否适用于这种情况,但它应该适用相同的规则。
如果您反复在许多不同的对象上调用instanceof
或method_exists
,上述示例显然不适用 - 但我建议您专注于代码简单性,可读性和重复数据删除,因为此处显示的示例显示每个选项的处理时间差异可以忽略不计。
不存在
就像事后的想法一样,我再次运行相同的检查,这次寻找一个不存在的方法,一个未实现的接口,结果与以前几乎相同。
答案 3 :(得分:0)
@Ashish Awasthi
我知道这是一个老问题,但是,我想把2便士丢进去...
如果您使用的是OOP,则正确答案(IMHO)是instanceof,否 method_exists。
method_exists将仅返回一个布尔值,告诉您该方法是否已定义。但是instanceof保证该方法将存在并且该方法的定义将采用预期的格式,例如:它将存在,并且该方法期望2个参数(或3个参数,或者您可能需要许多参数)已为您的方法定义)。而且,如果您使用了类型提示,那么instanceof也将确保参数(和返回值)的格式符合预期。 method_exists无法执行任何操作!