PHP中的::(双冒号)和 - >(箭头)有什么区别?

Joe*_*Joe 184 php

在PHP中有两种不同的方法来访问方法,但有什么区别?

$response->setParameter('foo', 'bar');
Run Code Online (Sandbox Code Playgroud)

sfConfig::set('foo', 'bar');
Run Code Online (Sandbox Code Playgroud)

我假设->(用大于号或破坏号的破折号)用于变量的函数,而::(双冒号)用于类的函数.正确?

=>赋值运算符仅用于一个阵列中分配的数据?这与=用于实例化或修改变量的赋值运算符形成对比吗?

Art*_*cto 166

当左侧部分是对象实例时,您使用->.否则,你使用::.

这意味着它->主要用于访问实例成员(虽然它也可以用于访问静态成员,不鼓励这样使用),而::通常用于访问静态成员(尽管在一些特殊情况下,它用于访问实例成员) ).

一般情况下,::被用于范围的分辨率,并且它可以具有一个类名称,parent,self,或(在PHP 5.3)static到其左边.parent指的是使用它的类的超类的范围; self是指使用它的类的范围; static指的是"被调用的范围"(参见后期静态绑定).

规则是::当且仅当以下情况时,调用with 是实例调用:

  • 目标方法未声明为静态
  • 在调用时有一个兼容的对象上下文,这意味着必须为true:
    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";
Run Code Online (Sandbox Code Playgroud)

输出:

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

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

$b->func_instance():
in B::func_instance
in A::func_instance
in A::func_instance

$a->dyn():
in A::callDynamic
in dynamic dyn (__callStatic)

$b->dyn():
in A::callDynamic
in dynamic dyn (__call)

  • @lucideer在静态方法的情况下,这是一个良好实践的问题(该方法属于类本身),但如果使用` - >`调用静态方法,PHP不会抱怨.当然,您可能需要实例化该类只是为了调用静态方法,因此也会影响性能.但是,对于属性,还有更多问题.提出了严格警告,[可能有效也可能无效](http://codepad.viper-7.com/d3oH0Q).请注意反过来也是如此 - 您可以静态调用实例方法,但这更糟糕(并且您不能在此类方法实现中使用`$ this`). (4认同)
  • "` - >`主要用于访问实例成员(虽然它也可以用来访问静态成员,但不建议这样使用)"我不知道它可能是.因此,如果它在用于访问静态成员时以某种方式"起作用" - 如果一个人不正确地使用它,那么行为会有什么不同?只是出于好奇. (3认同)

Cro*_*zin 49

::用于静态上下文,即.当某个方法或属性声明为static时:

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

$result = Math::sin(123);
Run Code Online (Sandbox Code Playgroud)

此外,当您调用父类的方法/属性时,::操作符(Scope Resolution Operator,又名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);
    }
}
Run Code Online (Sandbox Code Playgroud)

->用于动态上下文,即.当你处理某些类的某个实例时:

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

$h = new Hello();
$h->say();
Run Code Online (Sandbox Code Playgroud)

顺便说一下:当你没有任何OOP经验时,我不认为使用Symfony是个好主意.


Mri*_*hal 23

实际上通过这个符号,我们可以调用一个静态的类方法,而不依赖于其他初始化......

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

这里doWrite()函数不依赖于任何其他方法或变量,它是一个静态方法.这就是为什么我们可以通过这个运算符调用这个方法而不初始化这个类的对象.

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

但是如果你想以write这种方式调用方法,它将产生一个错误,因为它依赖于初始化.


cas*_*nca 15

=>运算符用于在关联数组指派键值对.例如:

$fruits = array(
  'Apple'  => 'Red',
  'Banana' => 'Yellow'
);
Run Code Online (Sandbox Code Playgroud)

它的含义在foreach声明中类似:

foreach ($fruits as $fruit => $color)
  echo "$fruit is $color in color.";
Run Code Online (Sandbox Code Playgroud)


Dea*_*ado 13

静态和实例化方法和属性之间的区别似乎是那些刚开始使用PHP 5中的OOP PHP的人的最大障碍之一.

当从静态上下文调用对象或属性时,使用双冒号运算符(从希伯来语称为Paamayim Nekudotayim - trivia).这意味着尚未创建对象的实例.

相反,箭头运算符调用来自对象实例的引用的方法或属性.

静态方法在链接到create和delete方法的数据库的对象模型中特别有用,因为您可以将返回值设置为inserted表id,然后使用构造函数按行id实例化对象.