instanceof или method_exist, какой из них следует использовать?

В моем классе проверки я передаю различные объекты класса, и мне нужно вызвать метод для этого класса. Теперь вопросы есть. Как я могу гарантировать, что метод существует.

Должен ли я использовать instanceof как это:

...
...
if($passedObject instanceof MyExpectedClass) {
//then call the rquired method
}
...
...

или должен пойти на method_exists как это:

...
...
if(method_exists($passedObject, 'MyExpectedMethod')) {
//then call the rquired method
}
...
...

Я сбит с толку. Какой из них лучше подходит.

РЕДАКТИРОВАТЬ

Я знаю, что если переданный Object является экземпляром ожидаемого класса, то ожидаемый метод также будет существовать, потому что MyExpected Class реализует мой интерфейс, который содержит ожидаемый метод. Надеюсь, что это даст больше ясности в сценарии.

0

Решение

Это две разные проверки: instanceof проверяет, является ли предоставленный объект экземпляром определенного класса, а method_exists проверяет, существует ли определенный метод в классе, поэтому первая проверка никогда не сообщит вам, если переданный объект содержит этот метод, только скажу вам, что это экземпляр этого метода. Вы должны использовать method_exists ()

Простые тесты

class MyClass {
public function myMethod() {
// code
}
}
$obj = new MyClass;
var_dump(method_exists($obj, 'myMethod')); // true
1

Другие решения

Вы можете сделать интерфейс:

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;
}
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 над многими различными объектами — но я бы посоветовал сосредоточиться на простоте кода, удобочитаемости и дедупликации усилий, потому что приведенный здесь пример показывает, что для каждого варианта есть незначительная разница во времени обработки.

Не существует

В качестве запоздалой мысли я снова выполнил те же проверки, на этот раз в поисках несуществующего метода и интерфейса, который не был реализован, и результаты были почти такими же, как и раньше.

0
По вопросам рекламы [email protected]