Яка різниця між: (подвійна двокрапка) та -> (стрілка) у PHP?


197

Є два різних способи доступу до методів у PHP, але яка різниця?

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

і

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

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

Чи використовується =>оператор призначення лише для призначення даних у масиві? Це на відміну від =оператора присвоєння, який використовується для створення екземпляра або зміни змінної?



Відповіді:


173

Коли ліва частина - це екземпляр об'єкта, ви використовуєте ->. В іншому випадку ви використовуєте ::.

Це означає, що ->він використовується в основному для доступу до членів екземплярів (хоча він також може бути використаний для доступу до статичних членів, таке використання не рекомендується), в той час ::як зазвичай використовується для доступу до статичних членів (хоча в деяких особливих випадках він використовується для доступу до членів екземплярів ).

Загалом, ::використовується для дозволу області видимості , і вона може мати або ім'я класу, parent, selfабо (в PHP 5.3) staticзліва від нього . parentпосилається на область надкласу класу, де він використовується; selfпосилається на область класу, де він використовується; staticвідноситься до "названої області" (див. пізні статичні прив'язки ).

Правило полягає в тому, що виклик з ::- це виклик екземпляра, якщо і лише тоді:

  • цільовий метод не оголошується статичним і
  • на момент виклику є сумісний контекст об'єкта, тобто це має бути правдою:
    1. виклик проводиться з контексту, де $thisіснує і
    2. клас of $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 значення
B :: func_static (): в B :: func_static

$ b-> prop_instance: B :: $ prop_instance значення
$ b-> func_static (): в B :: func_static

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

$ a-> dyn ():
в A :: callDynamic
в динамічному dyn (__callStatic)

$ b-> dyn ():
в A :: callDynamic
в динамічному dyn (__call)

3
" ->використовується в основному для доступу до членів екземплярів (хоча він також може бути використаний для доступу до статичних членів, таке використання не рекомендується)" Я не знав, що це може бути. Тож, якщо він "функціонує" якимось чином, коли використовується для доступу до статичних членів - яку різницю в поведінці можна було б очікувати, якщо користуватися нею неправильно, як це? Тільки з цікавості.
lucideer

4
@lucideer У разі статичних методів це питання належної практики (метод належить до самого класу), але PHP не скаржиться, якщо викликає статичний метод ->. Звичайно, вам може знадобитися інстанціювати клас просто для виклику статичного методу, тому також є хіт продуктивності. Однак із властивостями виникає більше проблем. Піднімається попередження STRICT, яке може працювати або не працювати . Зауважте, що і зворотний факт є вірним - ви можете викликати метод екземпляра статично, але це ще гірше (і ви не можете використовувати $thisв такій реалізації методу).
Артефакто

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 - це не дуже гарна ідея, коли у вас немає досвіду OOP.


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

Різниця між статичними та інстанційними методами та властивостями, здається, є однією з найбільших перешкод для тих, хто тільки починається з OOP PHP у PHP 5.

Оператор подвійної товстої кишки (який з івриту називається Paamayim Nekudotayim - дрібниці) використовується при виклику об'єкта чи властивості зі статичного контексту. Це означає, що примірник об'єкта ще не створений.

Оператор зі стрілками, навпаки, називає методи або властивості, які посилаються на посилання на екземпляр об'єкта.

Статичні методи можуть бути особливо корисними в об'єктних моделях, які пов'язані з базою даних для методів створення та видалення, оскільки ви можете встановити повернене значення на вставлений ідентифікатор таблиці, а потім використовувати конструктор для інстанціювання об'єкта за ідентифікатором рядка.


2

Так, я просто вдарив першим 'PHP Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM'. Моє погано, у мене було таке, $instance::method()що повинно було бути $instance->method(). Дурний мене.

Дивно, що це все ще працює чудово на моїй локальній машині (працює на PHP 5.3.8) - нічого, навіть попередження з error_reporting = E_ALL - але зовсім не на тестовому сервері, там він просто вибухає синтаксичною помилкою і білий екран у браузері. Оскільки журнал PHP було вимкнено на тестовій машині, а хостинг-компанія була надто зайнята, щоб його включити, це було не надто очевидно.

Отже, слово попередження: мабуть, деякі установки PHP дозволять вам використовувати $ instance :: method (), а інші -.

Якщо хтось може розширити, чому це так, будь ласка, зробіть це.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.