вызывать статический метод внутри класса?


166

Как вызвать статический метод из другого метода в том же классе?

$this->staticMethod();

или

$this::staticMethod();

13
Вы можете быть заинтересованы в этом ( selfпротив $this): stackoverflow.com/questions/151969/php-self-vs-this
Феликс Клинг

Просто FYI, ваш первый пример - переменная экземпляра, вызывающая статический метод, который невозможен, потому что статический метод является частью класса и недоступен через переменную экземпляра.
Joejoeson

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

Ответы:


322

...но почему? $ this-> staticMethod () тоже работает. Можете ли вы объяснить, почему self :: staticMethod () более правильно (если это так)?
Ян Данн

29
@Ian Dunn Проще говоря, $thisсуществует , только если объект был создан, и вы можете использовать только $this->methodиз существующего объекта. Если у вас нет объекта, но вы просто вызываете статический метод, и в этом методе вы хотите вызвать другой статический метод в том же классе, вы должны использовать self::. Поэтому, чтобы избежать потенциальных ошибок (и строгих предупреждений), лучше использовать self.
Йерун

1
Спасибо! В laravel я обнаружил, что случайно вызывал статический метод через расширенный контроллер $this, но проблема не возникала до тех пор, пока код не был передан stage. ошибок не возвращалось, значение было просто 0. будьте осторожны с этим, используйтеself::
бля

44

Давайте предположим, что это ваш класс:

class Test
{
    private $baz = 1;

    public function foo() { ... }

    public function bar() 
    {
        printf("baz = %d\n", $this->baz);
    }

    public static function staticMethod() { echo "static method\n"; }
}

Из foo()метода, давайте посмотрим на различные варианты:

$this->staticMethod();

Так что это вызывает staticMethod()как метод экземпляра, верно? Это не. Это потому, что метод объявлен как public staticинтерпретатор, будет вызывать его как статический метод, поэтому он будет работать как положено. Можно утверждать, что это делает из кода менее очевидным, что происходит статический вызов метода.

$this::staticMethod();

Начиная с PHP 5.3 вы можете использовать, $var::method()чтобы означать <class-of-$var>::; это довольно удобно, хотя приведенный выше вариант использования все еще довольно нетрадиционен. Итак, это приводит нас к наиболее распространенному способу вызова статического метода:

self::staticMethod();

Теперь, прежде чем вы начинаете думать , что ::это оператор статического вызова, позвольте мне дать вам еще один пример:

self::bar();

Это напечатает baz = 1, что означает, что $this->bar()и self::bar()делать то же самое; это потому, что ::это просто оператор разрешения области видимости. Это там , чтобы сделать parent::, self::и static::работу , и вы получите доступ к статическим переменным; способ вызова метода зависит от его сигнатуры и способа вызова.

Чтобы увидеть все это в действии, посмотрите этот вывод 3v4l.org .


self::bar()кажется вводящим в заблуждение - это теперь осуждается? (используется self::для вызова метода экземпляра, а не статического метода).
ToolmakerSteve

@ToolmakerSteve, как бы вы сказали, что это вводит в заблуждение?
Ja͢ck

Логически говоря, нет selfпри вызове статического метода. По определению: статический метод вызывается из любого места и не получает параметр «self». Тем не менее, я вижу удобство этого phpсинтаксиса, так что вам не нужно писать MyClassName::. Я привык к языкам со статической типизацией, где компилятору должны быть указаны все переменные, доступные в текущей области видимости, поэтому (эквивалент) self::может быть опущен. Так сказал только один self instanceMethod; нет причин говорить self staticMethod.
ToolmakerSteve

15

Это очень поздний ответ, но он добавляет некоторые детали к предыдущим ответам

Когда речь идет о вызове статических методов в PHP из другого статического метода в том же классе, важно различать selfимя класса.

Возьмите для примера этот код:

class static_test_class {
    public static function test() {
        echo "Original class\n";
    }

    public static function run($use_self) {
        if($use_self) {
            self::test();
        } else {
            $class = get_called_class();
            $class::test(); 
        }
    }
}

class extended_static_test_class extends static_test_class {
    public static function test() {
        echo "Extended class\n";
    }
}

extended_static_test_class::run(true);
extended_static_test_class::run(false);

Выход этого кода:

Оригинальный класс

Расширенный класс

Это потому, что selfотносится к классу, в котором находится код, а не к классу кода, из которого он вызывается.

Если вы хотите использовать метод, определенный в классе, который наследует исходный класс, вам нужно использовать что-то вроде:

$class = get_called_class();
$class::function_name(); 

2
Я нашел это информативным. Небольшая гнида, я бы не сказал, что другие ответы "вводят в заблуждение". Точнее сказать, что они «неполные»; они не решают (не заданный) вопрос о том, что self::происходит в (редком) случае, когда статический метод A вызывает другой статический метод B, а B был переопределен в подклассе. ИМХО, менее запутанно ограничивать переопределение метода методами «экземпляра»; используйте эту способность экономно на статическом уровне. Другими словами, читатели вашего кода ожидают переопределения методов экземпляров (что является сущностью ОО-кодирования), но не статических.
ToolmakerSteve

1
Очень полезно и имеет смысл, что расширение класса не является исходным классом. Следовательно, очевидно, selfчто в этом случае оно не будет использовано. Вы объявили отдельный класс как расширение первого класса. Использование selfв расширенном классе будет ссылаться на расширенный класс. Это не противоречит другим ответам, но, безусловно, помогает продемонстрировать масштаб self.
Айрин

2

В более поздней версии PHP self::staticMethod();также не будет работать. Это бросит строгую стандартную ошибку.

В этом случае мы можем создать объект того же класса и вызвать объект

вот пример

class Foo {

    public function fun1() {
        echo 'non-static';   
    }

    public static function fun2() {
        echo (new self)->fun1();
    }
}

Вы можете сделать это, хотя, если fun1не используете self, не логично делать это методом экземпляра. Правильный способ сделать это в PHP, чтобы объявить public static function fun1, а затем вызвать, указав класс: Foo::fun1. Я уверен, что это намеченный способ исправить эту строгую стандартную ошибку.
ToolmakerSteve
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.