PHP有两种不同的访问方法,但它们之间有什么区别?
$response->setParameter('foo', 'bar');
和
sfConfig::set('foo', 'bar');
我假设 ->
(带有大于符号或尖括号的破折号)用于变量的函数,而::
(双冒号)用于类的函数。这样正确吗?
=>
赋值运算符是否仅用于在数组中分配数据?与用于实例化或修改变量的=
赋值运算符相比如何?
PHP有两种不同的访问方法,但它们之间有什么区别?
$response->setParameter('foo', 'bar');
和
sfConfig::set('foo', 'bar');
我假设 ->
(带有大于符号或尖括号的破折号)用于变量的函数,而::
(双冒号)用于类的函数。这样正确吗?
=>
赋值运算符是否仅用于在数组中分配数据?与用于实例化或修改变量的=
赋值运算符相比如何?
->
。否则,使用::
。->
主要用于访问实例成员(虽然它也可以用于访问静态成员,但这样的用法是不鼓励的),而::
通常用于访问静态成员(虽然在一些特殊情况下,它也被用于访问实例成员)。::
用于scope resolution,它可以左侧有类名、parent
、self
或(在PHP 5.3中)static
。 parent
指的是其使用的超类的范围;self
指的是其使用的类的范围;static
指的是“调用作用域”(请参阅late static bindings)。::
进行调用仅在以下情况下才是实例调用:
$this
的上下文中进行的,并且$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中 在dynamic dyn (__callStatic)中 $b->dyn(): 在A::callDynamic中 在dynamic dyn (__call)中
->
调用静态方法,它不会抱怨。当然,您可能需要实例化该类才能调用静态方法,所以性能有所下降。然而,对于属性来说,存在更多问题。严格模式将引发警告,并且它可能或可能不起作用。请注意,反过来也是正确的-您可以静态地调用实例方法,但这甚至更糟糕(并且无法在此类方法实现中使用$this
)。 - Artefacto::
用于静态上下文,即当某个方法或属性被声明为静态时使用:
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。
实际上,通过这个符号,我们可以调用一个静态的类方法,而且不依赖于其他初始化...
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');
// 输出:Hello Mrinmoy.
但如果您想以这种方式调用write
方法,它将生成一个错误,因为它依赖于初始化。
=>
运算符用于在关联数组中分配键值对。例如:
$fruits = array(
'Apple' => 'Red',
'Banana' => 'Yellow'
);
它在foreach
语句中的意思类似:
foreach ($fruits as $fruit => $color)
echo "$fruit is $color in color.";
对于那些刚开始学习PHP 5面向对象编程的人来说,静态和实例化方法以及属性之间的区别似乎是最大的障碍之一。
双冒号运算符(在希伯来语中被称为Paamayim Nekudotayim - 幸存者)用于从静态上下文中调用对象或属性。这意味着尚未创建对象的实例。
相反地,箭头运算符调用从对象实例的引用中调用的方法或属性。
在链接到数据库的对象模型中使用静态方法可以特别有用,用于创建和删除方法,因为您可以将返回值设置为插入表ID,然后使用构造函数按行ID实例化对象。
是的,我刚刚遇到了我的第一个'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(),而其他安装程序不允许。
如果有人能够解释为什么会这样,请分享一下。