草庐IT

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

coder 2024-01-04 原文

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

最佳答案

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

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

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

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

static 到底是什么意思?静态方法和属性是指所有当前和 future 的类实例共享的类方法和属性。如果 A::$foo 被声明为:

private static $foo;

那么您的代码中所有类 A 将只有一个 $foo。更改 $foo 会影响类 A 的所有实例,并且甚至无需创建该类的实例即可访问 $foo(如 >新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 修改或访问非静态属性,这将是一个 fatal error 。你不能那样做。

在PHP的error_reporting中,show all errors的E_ALL设置实际上并不包含严格警告。这必须通过 E_ALL & E_STRICT 来完成。

关于PHP:为什么我会收到有关静态属性的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6337543/

有关PHP:为什么我会收到有关静态属性的错误?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  3. ruby-on-rails - Rails 常用字符串(用于通知和错误信息等) - 2

    大约一年前,我决定确保每个包含非唯一文本的Flash通知都将从模块中的方法中获取文本。我这样做的最初原因是为了避免一遍又一遍地输入相同的字符串。如果我想更改措辞,我可以在一个地方轻松完成,而且一遍又一遍地重复同一件事而出现拼写错误的可能性也会降低。我最终得到的是这样的:moduleMessagesdefformat_error_messages(errors)errors.map{|attribute,message|"Error:#{attribute.to_s.titleize}#{message}."}enddeferror_message_could_not_find(obje

  4. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  5. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  6. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  7. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  8. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  9. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

    它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

  10. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

随机推荐