PHP: Почему я получаю ошибки о статических свойствах? - PullRequest
5 голосов
/ 14 июня 2011

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 "what"};} нельзя получить доступ с помощью метода :: read (), поскольку необходим оператор ->). Кроме того, статические свойства не могут быть доступны объектному коду, даже если они существуют внутри функции (например, класс A {static $ variable; function read () {echo $ this-> variable};} a-> read (); won не работает, потому что оператор -> используется для доступа к функции, которая вызывает статическое свойство.). Изменив метод и свойство на static, доступ к методу можно получить с помощью статических средств. Изменение как метода, так и свойства на нестатическое делает его таким, чтобы к любому из них можно было обращаться с помощью экземпляра объекта. Мне не имеет смысла, что отладчик выдает ошибки, потому что моя книга говорит, что статические свойства можно вызывать из нестатических методов через вызовы объектного кода для нестатических методов. Итак, отладчик сломан? Потому что я пробовал каждую комбинацию, и код, кажется, работает, только если метод и свойство являются статическими или нестатическими. : (((

Ответы [ 3 ]

12 голосов
/ 14 июня 2011

Часть строгих стандартов связана с тем, что 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.

3 голосов
/ 14 июня 2011

:: используется для доступа к статическому атрибуту. Если вы хотите получить доступ к атрибуту объекта, используйте ->.

$a->read();

...

echo $this->$foo;
2 голосов
/ 14 июня 2011

Хотя другие ответы однозначно верны, вот ответ на ваш конкретный вопрос:

Мне не имеет смысла, что отладчик выдает ошибки, потому что моя книга говорит, что статические свойства могутвызываться из нестатических методов через вызовы объектного кода для нестатических методов.Итак, отладчик сломан?Потому что я пробовал каждую комбинацию, и код, кажется, работает, только если метод и свойство являются статическими или нестатическими.: (((

У автора вашей книги сложилось впечатление, что отсутствие сообщения об ошибке считается чистым кодом. Это не так. У вас не должно быть метода, который можно вызывать статически кака также динамически, так как эти два просто слишком сильно различаются. Динамические вызовы предназначены для объектов, где статические вызовы предназначены для классов. Если у вас есть возможность, я всегда стараюсь идти динамическим путем, поскольку это приводит к меньшей связности в приложении.

Относительно того, почему «отладчик выдает ошибки» (это интерпретатор, который выдает предупреждения E_STRICT, но эй;)): это поведение было изменено в PHP с пятью точками. В PHP 4 вы можете вызывать каждый метод статически, даже если это был динамический метод. Возможно, ваша книга отстает от фактов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...