В чем разница между :: (двойное двоеточие) и -> (стрелка) в PHP?

197

Есть два разных способа доступа к методам в PHP, но в чем разница?

$response->setParameter('foo', 'bar');

и

sfConfig::set('foo', 'bar');

Я предполагаю ->(тире со знаком больше, чем знак или шеврон) используется для функций для переменных, и:: (двойные двоеточия) используется для функций для классов. Верный?

Является ли =>оператор присваивания используется только для назначения данных в массиве? Это в отличие от =оператора присваивания, который используется для создания или изменения переменной?

Джо
источник
3
Возможный дубликат ссылки. Что означает этот символ в PHP?
Гордон
1
Возможный дубликат Разницы между двойными двоеточиями и стрелками в PHP?
Органический адвокат

Ответы:

173

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

Это означает, что ->в основном используется для доступа к членам экземпляра (хотя он также может использоваться для доступа к статическим членам, такое использование не рекомендуется), в то время как:: обычно используется для доступа к статическим членам (хотя в некоторых особых случаях он используется для доступа к членам экземпляра). ).

Как правило, ::используется для разрешения области видимости и может иметь либо имя класса parent, selfлибо, либо (в PHP 5.3) staticслева от него. parentотносится к области действия суперкласса класса, в котором он используется; selfотносится к области действия класса, в котором он используется; staticотносится к «вызываемой области видимости» (см. поздние статические привязки ).

Правило состоит в том, что вызов with ::является вызовом экземпляра тогда и только тогда, когда:

  • целевой метод не объявлен как статический и
  • во время вызова существует совместимый контекст объекта, что означает, что они должны быть истинными:
    1. вызов сделан из контекста, где $thisсуществует и
    2. класс $this- это либо класс вызываемого метода, либо его подкласс.

Пример:

class A {
    public function func_instance() {
        echo "in ", __METHOD__, "\n";
    }
    public function callDynamic() {
        echo "in ", __METHOD__, "\n";
        B::dyn();
    }

}

class B extends A {
    public static $prop_static = 'B::$prop_static value';
    public $prop_instance = 'B::$prop_instance value';

    public function func_instance() {
        echo "in ", __METHOD__, "\n";
        /* this is one exception where :: is required to access an
         * instance member.
         * The super implementation of func_instance is being
         * accessed here */
        parent::func_instance();
        A::func_instance(); //same as the statement above
    }

    public static function func_static() {
        echo "in ", __METHOD__, "\n";
    }

    public function __call($name, $arguments) {
        echo "in dynamic $name (__call)", "\n";
    }

    public static function __callStatic($name, $arguments) {
        echo "in dynamic $name (__callStatic)", "\n";
    }

}

echo 'B::$prop_static: ', B::$prop_static, "\n";
echo 'B::func_static(): ', B::func_static(), "\n";
$a = new A;
$b = new B;
echo '$b->prop_instance: ', $b->prop_instance, "\n";
//not recommended (static method called as instance method):
echo '$b->func_static(): ', $b->func_static(), "\n";

echo '$b->func_instance():', "\n", $b->func_instance(), "\n";

/* This is more tricky
 * in the first case, a static call is made because $this is an
 * instance of A, so B::dyn() is a method of an incompatible class
 */
echo '$a->dyn():', "\n", $a->callDynamic(), "\n";
/* in this case, an instance call is made because $this is an
 * instance of B (despite the fact we are in a method of A), so
 * B::dyn() is a method of a compatible class (namely, it's the
 * same class as the object's)
 */
echo '$b->dyn():', "\n", $b->callDynamic(), "\n";

Вывод:

B :: $ prop_static: B :: $ prop_static value
B :: func_static (): в B :: func_static

$ b-> prop_instance: B :: $ prop_instance value
$ b-> func_static (): in B :: func_static

$ B-> func_instance ():
в B :: func_instance
в A :: func_instance
в A :: func_instance

$ A-> динам ():
в A :: callDynamic
в динамическом dyn (__callStatic)

$ B-> динам ():
в A :: callDynamic
в динамическом dyn (__call)
Artefacto
источник
3
«В ->основном используется для доступа к членам экземпляра (хотя он также может использоваться для доступа к статическим членам, такое использование не рекомендуется)» Я не знал, что это может быть. Так что, если он «функционирует» каким-то образом, когда используется для доступа к статическим элементам - какую разницу в поведении можно ожидать, если использовать его неправильно, как это? Просто из любопытства.
Люцидер
4
@lucideer В случае статических методов это вопрос хорошей практики (метод принадлежит самому классу), но PHP не жалуется, если вызывает статический метод с ->. Конечно, вам может понадобиться создать экземпляр класса просто для вызова статического метода, так что есть также снижение производительности. Со свойствами, однако, есть больше проблем. СТРОГО предупреждение выдано, и оно может или не может работать . Обратите внимание, что верно и обратное - вы можете вызывать метод экземпляра статически, но это еще хуже (и вы не можете использовать $thisв такой реализации метода).
Artefacto
52

::используется в статическом контексте, т.е. когда какой-либо метод или свойство объявлено как статическое:

class Math {
    public static function sin($angle) {
        return ...;
    }
}

$result = Math::sin(123);

Кроме того, ::оператор (оператор разрешения области действия, также известный как Paamayim Nekudotayim ) используется в динамическом контексте, когда вы вызываете метод / свойство родительского класса:

class Rectangle {
     protected $x, $y;

     public function __construct($x, $y) {
         $this->x = $x;
         $this->y = $y;
     }
}

class Square extends Rectangle {
    public function __construct($x) {
        parent::__construct($x, $x);
    }
}

->используется в динамическом контексте, т.е. когда вы имеете дело с некоторым экземпляром некоторого класса:

class Hello {
    public function say() {
       echo 'hello!';
    }
}

$h = new Hello();
$h->say();

Кстати: я не думаю, что использование Symfony - это хорошая идея, когда у вас нет опыта ООП.

Crozin
источник
24

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

class Test {

    public $name;

    public function __construct() {
        $this->name = 'Mrinmoy Ghoshal';
    }

    public static function doWrite($name) {
        print 'Hello '.$name;
    }

    public function write() {
        print $this->name;
    }
}

Здесь doWrite()функция не зависит от любого другого метода или переменной и является статическим методом. Вот почему мы можем вызывать этот метод этим оператором без инициализации объекта этого класса.

Test::doWrite('Mrinmoy'); // Output: Hello Mrinmoy.

Но если вы захотите вызвать writeметод таким способом, он выдаст ошибку, потому что он зависит от инициализации.

Мринмой Гошал
источник
16

=>Оператор используется для присвоения пар ключ-значение в ассоциативном массиве. Например:

$fruits = array(
  'Apple'  => 'Red',
  'Banana' => 'Yellow'
);

Это значение похоже на foreachутверждение:

foreach ($fruits as $fruit => $color)
  echo "$fruit is $color in color.";
Касабланка
источник
14

Разница между статическими и экземплярами методов и свойств представляется одним из главных препятствий для тех, кто только начинает работать с ООП PHP в PHP 5.

Оператор с двойным двоеточием (называемый Paamayim Nekudotayim с иврита - пустяки) используется при вызове объекта или свойства из статического контекста. Это означает, что экземпляр объекта еще не создан.

Оператор стрелки, наоборот, вызывает методы или свойства, которые ссылаются на экземпляр объекта.

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

DeaconDesperado
источник
2

Да, я просто ударил меня первый 'PHP Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM'. Мой плохой, у меня было то, $instance::method()что должно было быть $instance->method(). Я такой глупый.

Странно то, что на моем локальном компьютере это все еще работает очень хорошо (работает PHP 5.3.8) - ничего, даже предупреждения с ошибкой_портажа = E_ALL - но совсем не на тестовом сервере, там он просто взрывается с синтаксической ошибкой и белый экран в браузере. Так как логирование PHP было отключено на тестовом компьютере, и хостинговая компания была слишком занята, чтобы включить его, это было не слишком очевидно.

Итак, предупреждение: очевидно, некоторые установки PHP позволят вам использовать $ instance :: method (), а другие - нет.

Если кто-нибудь может объяснить, почему это так, пожалуйста.

PapaFreud
источник