PHP:为什么我会收到有关静态属性的错误?

时间:2011-06-13 23:26:10

标签: php static

http://codepad.viper-7.com/I0Zqoi

我不明白这有什么问题,或者如何解决它或为什么。对于编程有一点了解的人可以解释一下幕后发生的事情,比如在翻译层面吗?另外,我如何解决我的问题,为什么我需要以纠正的方式编写我的代码?你能用人类的语言告诉我,这有什么问题以及如何让它变得更好?我想我的书不能很好地解释,其中的代码不起作用。 :/谢谢你。

class A 
{
  private $foo = 'bar';
  function read()
  {
      echo self::$foo;
  }
}

$a = new A();
a::read();

Strict Standards: Non-static method A::read() should not be called statically in /code/I0Zqoi on line 13

Fatal error: Access to undeclared static property: A::$foo in /code/I0Zqoi on line 8

唯一的解决方法似乎是在方法前添加“static”。显然,非静态方法不能通过静态方法访问(例如,类A {function read(){echo“whatever”};}不能被:: read()访问,因为 - >运算符是必需的)。此外,目标代码无法访问静态属性,即使它们存在于函数中(例如,类A {static $ variable; function read(){echo $ this-> variable};} a-> read() ;将无法工作,因为 - >运算符用于访问调用静态属性的函数。)。通过将方法和属性都更改为静态,可以通过静态方式访问该方法。通过将方法和属性更改为非静态,使得可以使用对象实例访问任一方法。对我来说调试器抛出错误是没有意义的,因为我的书说静态属性可以通过非静态方法通过目标代码调用从非静态方法调用。那么,调试器坏了吗?因为我已经尝试了所有组合,并且只有方法和属性都是静态或非静态时,代码似乎才有效。 :(((

3 个答案:

答案 0 :(得分:12)

严格标准部分是因为a::read()是在::的静态上下文中调用的。在将$a声明为A的类实例后,您应该使用read()运算符调用变量上的->方法:

// Proper non-static method call
$a = new A();
$a->read();

在类定义中,$foo被声明为私有属性,但没有static关键字。然后使用::运算符而不是->在静态上下文中引用它。访问它的正确方法是L

// Proper reference to non-static $foo
function read() {
  echo $this->foo;
}

现在static的意思是什么?静态方法和属性引用所有当前和未来类实例共享的类方法和属性。如果A::$foo已被声明为:

private static $foo;

然后代码中只有$fooA类。更改$foo会影响所有类A的实例,并且即使创建了类的实例(例如$foo),也可以访问new A();

同样,可以在不创建类实例的情况下调用静态方法,因为它们不会修改非静态的类属性。

// Static method call:
A::read();

要将属性和方法声明为static,只需添加static关键字:

// Property
private static $foo;

// Method
public static function foo() {}

编辑更多示例

class A
{
  // Private property (non-static)
  private $foo;

  // Public property (static)
  public static $bar = 12345;

  // Public (non-static) function to access private $foo
  public function getFoo() { return $this->foo; }

  // Public (non-static) function to set private $foo
  public function setFoo($newfoo) { $this->foo = $newfoo; }

  // Static function 
  public static function incrementBar() { self::$bar++; }
}

现在看到它在行动:

// We haven't created any class instances yet (with the 'new' operator)
// But we can access the static properties & functions:

echo A::$bar . " ";
// prints 12345

A::incrementBar();
echo A::$bar . "\n";
// prints 12346

// Now we'll start working with class instances.
// Create 2 instances of class A
$a = new A();
$a->setFoo(8888);
$b = new A();
$b->setFoo(9999);

// It's a violation of strict standards to call getFoo() statically
// And it's meaningless to do so, because $foo only exists inside a class instance!

// Can't do this... Issues a strict warning since we're calling non-static getFoo() statically
//echo A::getFoo();


// But we can call getFoo() on the class instances:
echo $a->getFoo() . " " . $b->getFoo() . "\n";
// Prints 8888 9999

// Remember $bar was 12346...
echo $a::$bar . " " . $b::$bar . "\n";
// Prints 12346 12346

// Now modify the static property $bar again
// This affects all class instances.
A::incrementBar();
echo $a::$bar . " " . $b::$bar . "\n";
// Prints 12347 12347

我也把这整个东西塞进了键盘:http://codepad.viper-7.com/tV6omK

你正在阅读的书一定不要注意严格的标准。如果非静态函数不尝试访问/修改非静态属性,则可以静态成功调用它,但它会发出严格警告。如果非静态函数确实使用$this->property修改或访问非静态属性,那将是致命错误。你不能这样做。

在PHP error_reporting中,显示所有错误的E_ALL设置实际上不包括严格警告。必须使用E_ALL & E_STRICT完成。

答案 1 :(得分:3)

::用于访问静态属性。如果要访问对象属性,请使用->

$a->read();

...

echo $this->$foo;

答案 2 :(得分:2)

虽然其他答案肯定是正确的,但这里是您具体问题的答案:

  

调试器抛出错误是没有意义的,因为我的书说静态属性可以通过对非静态方法的目标代码调用从非静态方法调用。那么,调试器坏了吗?因为我已经尝试了所有组合,并且只有方法和属性都是静态或非静态时,代码似乎才有效。 :(((

您图书的作者认为没有收到错误消息会被视为干净的代码。不是。你不应该有一个既可以静态也可以动态调用的方法,因为这两个方法差别太大。动态调用用于对象,其中静态调用用于类。如果你有机会,我会一直尝试采用动态方式,因为这会在应用程序中产生更少的耦合。

至于为什么“调试器正在抛出错误”(这是解释器抛出E_STRICT警告,但是嘿;)):这个行为已经在PHP五点改变了。在PHP 4中,您可以静态调用每个方法,即使它是动态方法。可能,你的书在事实上落后了。