【问题标题】:PHP: Why am I getting errors about static properties?PHP:为什么我会收到有关静态属性的错误?
【发布时间】:2011-06-13 23:26:10
【问题描述】:

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

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

【问题讨论】:

  • static private $foo ...static function read()。我会让其他人再次尝试向您解释所有这些......如果您真正尝试真正的实际问题可能会更有帮助,而不是这些人为的案例,其中不可能知道您实际尝试做什么。

标签: php static


【解决方案1】:

严格标准部分是因为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;

那么您的代码中将只有一个 $foo 用于所有类 A。更改$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 完成。

【讨论】:

  • 对不起,我一点也不明白。您真的可以将更改完全发布到键盘或代码块,并显示您更改了哪些行吗?我正在尝试访问静态方法,但我似乎无法以静态或非静态方式进行。
  • 如果我的理解正确,它们必须都是静态或非静态的,但如果我只想限制属性的范围,我必须通过设置我想要限制的属性来做到这一点私有或受保护。然后,我可以通过方法访问属性,但我不能直接访问属性,这——正如你显然读到我的问题——是我想要做的。
  • @Fohsap 我添加了一个新的大例子来说明。
  • @Fohsap 你明白了。为了限制范围,重要的是 private/public 关键字,而不是 static。要保护对属性的访问,请创建属性 private 并创建 public 访问器函数来设置/获取它。您还可以拥有privatestatic 属性,这些属性必须由函数访问,但它们的值由所有类实例共享。
【解决方案2】:

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

$a->read();

...

echo $this->$foo;

【讨论】:

【解决方案3】:

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

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

您的书的作者认为没有收到错误消息被认为是干净的代码。它不是。您不应该有一个既可以静态调用又可以动态调用的方法,因为两者差别太大了。动态调用是针对对象的,而静态调用是针对类的。如果有机会,我总是会尝试采用动态方式,因为这样会减少应用程序中的耦合。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    • 2021-11-11
    • 1970-01-01
    • 1970-01-01
    • 2020-11-05
    相关资源
    最近更新 更多