อะไรคือความแตกต่างระหว่าง :: (เครื่องหมายโคลอนคู่) และ -> (ลูกศร) ใน PHP


197

มีสองวิธีที่แตกต่างในการเข้าถึงวิธีการใน PHP แต่ความแตกต่างคืออะไร?

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

และ

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

ฉันสมมติว่า->(เครื่องหมายขีดที่มีเครื่องหมายหรือเครื่องหมายบั้ง) มากกว่าใช้สำหรับฟังก์ชันสำหรับตัวแปรและ::(เครื่องหมายโคลอนคู่) ใช้สำหรับฟังก์ชันสำหรับคลาส แก้ไข?

เป็น=>ผู้ประกอบการที่ได้รับมอบหมายมาใช้เฉพาะข้อมูลที่กำหนดภายในอาร์เรย์แล้ว? ตรงกันข้ามกับ=ผู้ดำเนินการที่ได้รับมอบหมายซึ่งใช้ในการยกตัวอย่างหรือแก้ไขตัวแปรหรือไม่?



คำตอบ:


173

->เมื่อส่วนด้านซ้ายเป็นวัตถุเช่นคุณใช้ ::มิฉะนั้นคุณใช้

ซึ่งหมายความว่า->ส่วนใหญ่จะใช้ในการเข้าถึงสมาชิกอินสแตนซ์ (แม้ว่าจะสามารถใช้ในการเข้าถึงสมาชิกแบบคงที่การใช้งานดังกล่าวหมดกำลังใจ) ในขณะที่::มักจะใช้ในการเข้าถึงสมาชิกแบบคงที่ (ในบางกรณีพิเศษ )

โดยทั่วไป::จะใช้สำหรับความละเอียดขอบเขตและมันอาจมีทั้งชื่อชั้นparent, selfหรือ (ใน PHP 5.3) staticด้านซ้ายของ parentอ้างถึงขอบเขตของซูเปอร์คลาสของคลาสที่ใช้งาน selfหมายถึงขอบเขตของคลาสที่ใช้ staticอ้างถึง "ขอบเขตที่เรียกว่า" (ดูการผูกแบบคงที่ในช่วงปลาย )

กฎคือการโทรด้วย::เป็นการโทรแบบอินสแตนซ์หาก:

  • วิธีการเป้าหมายไม่ได้ประกาศเป็นแบบคงที่และ
  • มีบริบทวัตถุที่เข้ากันได้ในเวลาที่โทรหมายถึงสิ่งเหล่านี้จะต้องเป็นจริง:
    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 ค่า
B :: func_static (): ใน B :: func_static

$ b-> prop_instance: B :: $ prop_instance ค่า
$ b-> func_static (): ใน B :: func_static

$ B-> func_instance ():
ใน B :: func_instance
ใน A :: func_instance
ใน A :: func_instance

$ a-> dyn ():
ใน A :: callDynamic
ในไดนามิก dyn (__callStatic)

$ B-> dyn ():
ใน A :: callDynamic
ในไดนามิก dyn (__call)

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 เป็นความคิดที่ดีเมื่อคุณไม่มีประสบการณ์ 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 จากภาษาฮิบรู - เรื่องไม่สำคัญ) ใช้เมื่อเรียกวัตถุหรือคุณสมบัติจากบริบทแบบคงที่ นี่หมายความว่าอินสแตนซ์ของวัตถุยังไม่ได้ถูกสร้างขึ้น

ตัวดำเนินการลูกศรตรงกันข้ามเรียกเมธอดหรือคุณสมบัติที่มาจากการอ้างอิงของอินสแตนซ์ของวัตถุ

วิธีสแตติกสามารถเป็นประโยชน์อย่างยิ่งในโมเดลวัตถุที่เชื่อมโยงกับฐานข้อมูลเพื่อสร้างและลบเมธอดเนื่องจากคุณสามารถตั้งค่าส่งคืนเป็น id ตารางที่แทรกจากนั้นใช้ constructor เพื่อสร้างอินสแตนซ์ของวัตถุด้วย id แถว


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 () ในขณะที่บางโปรแกรมไม่แสดง

หากใครสามารถขยายได้ว่าทำไมถึงเป็นเช่นนั้นโปรดทำ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.