PHP'de :: (çift kolon) ve -> (ok) arasındaki fark nedir?


197

PHP'de yöntemlere erişmenin iki farklı yolu vardır, ancak fark nedir?

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

ve

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

->Değişkenler için işlevler için ::( işaret veya chevrondan daha büyük çizgi) ve sınıflar için işlevler için (çift sütun) kullanıldığını varsayıyorum . Doğru?

Is =>atama operatörü yalnızca bir dizi içinde atama veri sağlamak için kullanılır? Bu, =bir değişkeni örneklemek veya değiştirmek için kullanılan atama işlecinin tersi midir?



Yanıtlar:


173

Sol kısım bir nesne örneği olduğunda, kullanırsınız ->. Aksi takdirde kullanırsınız ::.

Bu ->, çoğunlukla örnek üyelerine erişmek için kullanılır (statik üyelere erişmek için de kullanılabilir, ancak bu tür kullanım önerilmez), ancak ::genellikle statik üyelere erişmek için kullanılır (ancak birkaç özel durumda örnek üyelerine erişmek için kullanılır) ).

Genelde, ::kullanılan kapsam çözünürlük ve sahip olabilirler ya bir sınıf adı, parent, self, ya da (PHP 5.3) staticonun solunda. parent"Sınıf", kullanıldığı sınıfın üst sınıfının kapsamını ifade eder; selfsınıfın kullanıldığı sınıfın kapsamını ifade eder; static"kapsam" olarak adlandırılır ( geç statik bağlara bakınız ).

Kural şudur: ile yapılan bir çağrı ::yalnızca aşağıdaki durumlarda örnek çağrıdır:

  • hedef yöntem statik olarak bildirilmez ve
  • çağrı sırasında uyumlu bir nesne bağlamı vardır, yani bunlar doğru olmalıdır:
    1. çağrı, $thisvar olan bir bağlamdan yapılır ve
    2. sınıfı $thisya çağrılan yöntemin sınıfı ya da alt sınıfıdır.

Misal:

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";

Çıktı:

B :: $ prop_static: B :: $ prop_static değeri
B :: func_static (): içinde B :: func_static

$ b-> prop_instance: B :: $ prop_instance değeri
$ b-> func_static (): içinde B :: func_static

$ B-> func_instance ():
in B :: Instagram Hesabındaki Resim ve Videoları func_instance
içinde A :: func_instance
içinde A :: func_instance

$ A-> dyn ():
içinde A :: callDynamic
dinamik dyn'de (__callStatic)

$ B-> dyn ():
içinde A :: callDynamic
dinamik dyn'de (__call)

3
" ->Çoğunlukla örnek üyelere erişmek için kullanılır (ancak statik üyelere erişmek için de kullanılabilir, ancak bu tür kullanım önerilmez)" olabileceğinin farkında değildim. Eğer statik üyelere erişmek için kullanıldığında bir şekilde "işlev görürse" - eğer kişi yanlış bir şekilde böyle kullanacak olsaydı hangi davranış farkı beklenirdi? Sadece meraktan.
lucideer

4
@lucideer Statik yöntemler söz konusu olduğunda, bu iyi bir uygulamadır (yöntem sınıfın kendisine aittir), ancak statik bir yöntem çağrılırsa PHP şikayet etmez ->. Tabii ki, sadece statik bir yöntem çağırmak için sınıfı başlatmanız gerekebilir, bu yüzden bir performans isabeti de vardır. Bununla birlikte, özellikler ile daha fazla sorun var. Bir STRICT uyarısı verilir ve işe yarayıp yaramayabilir . Bunun tersinin de geçerli olduğunu unutmayın - statik olarak bir örnek yöntemini çağırabilirsiniz, ancak bu daha da kötüdür (ve $thisbu yöntem uygulamasında kullanamazsınız ).
Artefacto

52

::kullanılan statik bağlamda, yani. bazı yöntem veya özellikler statik olarak bildirildiğinde:

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

$result = Math::sin(123);

Ayrıca, bir üst sınıfın yöntemini / özelliğini çağırdığınızda , ::işleç (Kapsam Çözümleme İşleci, diğer adıyla Paamayim Nekudotayim ) dinamik bağlamda kullanılır:

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);
    }
}

->dinamik bağlamda kullanılır , yani. bazı sınıf örnekleriyle uğraşırken:

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

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

Bu arada: Symfony kullanmanın OOP deneyiminiz olmadığında iyi bir fikir olduğunu düşünmüyorum.


24

Aslında bu sembolle, statik olan ve diğer başlatmaya bağımlı olmayan bir sınıf yöntemi çağırabiliriz ...

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;
    }
}

Burada doWrite()işlev başka herhangi bir yönteme veya değişkene bağlı değildir ve statik bir yöntemdir. Bu yüzden bu yöntemi, bu sınıfın nesnesini başlatmadan bu operatör tarafından çağırabiliriz.

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

Ancak writeyöntemi bu şekilde çağırmak istiyorsanız , başlatmaya bağlı olduğu için bir hata oluşturur.


16

=>Operatör bir ilişkisel dizi içinde atama anahtar-değer çiftleri için kullanılır. Örneğin:

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

İfadede anlamı şudur foreach:

foreach ($fruits as $fruit => $color)
  echo "$fruit is $color in color.";

14

Statik ve somutlaştırılmış yöntemler ve özellikler arasındaki fark, PHP 5'te OOP PHP ile yeni başlayanların önündeki en büyük engellerden biri gibi görünüyor.

Statik bir bağlamdan bir nesne veya özellik çağrılırken çift kolon operatörü (İbranice - trivia'dan Paamayim Nekudotayim olarak adlandırılır) kullanılır . Bu, nesnenin bir örneğinin henüz oluşturulmadığı anlamına gelir.

Ok operatörü ise tersine, nesnenin bir örneğinin bir referansından gelen yöntemleri veya özellikleri çağırır.

Statik yöntemler, oluşturma ve silme yöntemleri için bir veritabanına bağlanan nesne modellerinde özellikle yararlı olabilir, çünkü döndürülen değeri eklenen tablo kimliğine ayarlayabilir ve daha sonra nesneyi satır kimliğiyle örneklemek için yapıcıyı kullanabilirsiniz.


2

Evet, sadece ilk vurdum 'PHP Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM'. Benim hatam, $instance::method()olması gereken bir şey vardı $instance->method(). Aptal bana.

Garip bir şey, bu hala yerel makinemde iyi çalışıyor (PHP 5.3.8 çalışıyor) - hiçbir şey, error_reporting = E_ALL ile bir uyarı bile değil - ama hiç test sunucusunda değil, sadece bir sözdizimi hatasıyla patlıyor ve tarayıcıda beyaz bir ekran. PHP günlük kaydı test makinesinde kapatıldığından ve barındırma şirketi bunu açmak için çok meşgul olduğundan, çok açık değildi.

Yani, uyarı kelimesi: görünüşe göre, bazı PHP kurulumları $ instance :: method () kullanmanıza izin verirken, diğerleri kullanmaz.

Eğer kimse bunun nedenini genişletebilirse, lütfen yap.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.