__callStatic(): создание объектов из статического контекста?

6 Dennis [2013-11-07 19:11:00]

Я смущен тем, как "статические" и "динамические" функции и объекты в PHP работают вместе, особенно в отношении __callStatic().

Как работает __callStatic():

У вас может быть обычный класс MyClass, где внутри класса вы можете статическую функцию, называемую __callStatic(), которая вызывается только когда MyClass не имеет статической функции по имени, которое вы хотите.

то есть. Я звоню MyClass::newFunction();

newFunction() называется статическим, но MyClass не объявили ли они это. Итак, тогда __callStatic() вызывается и внутри вы можете сказать

$myObject=new SomeOtherClass();
$myObject->newFunction();

который вызывает функцию, которую вы хотите, но на какой-то другой объект.

Краткая версия:

Другими словами, __callStatic() делает следующее:

MyClass::newFunction();

который скрывает это:

(new SomeOtherClass())->newFunction();

Скажи, что теперь? То, что выглядит как код, вызывающий статическую функцию из класса, оказывается вызывающим эту функцию из какого-то другого класса и вызывающим ее через экземпляр, а не статически.

Объясните это, пожалуйста!

Почему это было сделано? Можете ли вы сделать что-нибудь подобное в другом месте, например С++ или Java? Я ищу краткое и краткое, но информативное объяснение статических и динамических функций в языках, и в этом случае, будь то __callStatic() violates или conforms к большой картине языковых конструкций. Или это новая языковая конструкция целиком.

instantiation php static


3 ответа


6 Решение hek2mgl [2013-11-07 19:16:00]

__callStatic() предоставляет разработчикам возможность реагировать на вызовы методов static, даже если эти методы не существуют или недоступны извне класса (protected). Это полезно для генерации динамического генерического кода. Если вы не видите, как это полезно, вы, возможно, не нуждаетесь в этой функции в данный момент и должны продолжать изучать основы.


Пример: у вас есть этот класс:

class Test {

    protected static function myProtected($test) {
        var_dump(__METHOD__, $test);
    }

    public static function __callStatic($method, $args) {
        switch($method) {
            case 'foo' :
                echo 'You have called foo()';
                var_dump($args);
                break;

            case 'helloWorld':
                echo 'Hello ' . $args[0];
                break;

            case 'myProtected':
                return call_user_func_array(
                    array(get_called_class(), 'myProtected'),
                    $args
                );
                break;                      
        }

    }

}

Попробуйте позвонить:

// these ones does not *really* exist
Test::foo('bar');
Test::helloWorld('hek2mgl');

// this one wouldn't be accessible
Test::myProtected('foo');

Понял?


1 Dennis [2013-11-12 01:01:00]

Почему это было сделано?

Это экзистенциальный вопрос, но я думаю, что ответ "потому что вы можете". PHP - это динамический язык, и эти конструкции __call и __callStatic() показывают свою силу, и эта сила может быть полезна в некоторых ситуациях.

Можете ли вы сделать что-нибудь подобное в другом месте, например С++ или Java?

Нет. У них нет подобных магических методов.

Я ищу краткое и краткое, но информативное объяснение статических и динамических функций в языках

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

... __callStatic() нарушает или соответствует большой картине языковых конструкций. Или это новая языковая конструкция целиком.

Это конструкция динамического языка. Не уверен, что эта функциональность существует на всех динамических языках, но она работает в PHP. Это ничего не нарушает, просто вводит новую парадигму сквозных функций catch-all, когда вызываемая вами функция не существует/недоступна в текущей области.


1 Marlies [2013-11-07 19:40:00]

Я не совсем уверен, почему здесь важна __callStatic()?

Я не совсем понимаю разницу между:

class Foo {

  static function bar() {
    $obj = new Foo();
    $obj->quux();
  } 

  function quux() {
    return "whatever";
  }

}

и ваш пример? В обоих сценариях вы вызываете статический метод, который вызывает другой метод для объекта того же класса.

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

И знаете ли вы о __call? Он делает то же самое, что и __callStatic, но для объектов, а не для классов. Например. $Foo- > myMissingMethod(); будет идти в __call, если такой метод существует для класса, для которого $foo является экземпляром.