Объект со статическими свойствами и методами
Вы уже знаете, что статические свойства и методы можно использовать, не создавая объект класса. На самом деле, однако, класс может содержать как статические свойства и методы, так и обычные.
Давайте посмотрим, как с этим работать и
какие преимущества это дает. Пусть у нас
есть класс Test
одновременно и со
статическим свойством, и с обычным:
<?php
class Test
{
public static $staticProperty; // публичное статическое свойство
public $usualProperty; // обычное свойство
}
?>
Давайте, к примеру, поработаем с его обычным свойством:
<?php
$test = new Test; // создаем объект класса
$test->usualProperty = 'usual'; // записываем значение
echo $test->usualProperty; // выведет 'usual'
?>
А теперь используем статическое свойство, не создавая объект этого класса:
<?php
Test::$staticProperty = 'static'; // записываем значение
echo Test::$staticProperty; // выведет 'static'
?>
На самом деле, если у нас есть переменная с объектом класса, то у этой переменной также будет доступно статическое свойство:
<?php
$test = new Test; // создаем объект класса
$test::$staticProperty = 'static'; // записываем значение
echo $test::$staticProperty; // выведет 'static'
?>
Разницы нет - мы к одному и тому же статическому свойству можем обращаться и так, и так. Вот пример, иллюстрирующий это:
<?php
// Записываем значение еще ДО создания объекта:
Test::$staticProperty = 'static';
// Cоздаем объект класса:
$test = new Test;
// Выводим статическое свойство:
echo $test::$staticProperty; // выведет 'static'
?>
Вот еще пример:
<?php
// Cоздаем объект класса:
$test = new Test;
// Записываем значение в статическое свойство:
$test::$staticProperty = 'static';
// Выводим значение, обратившись к классу:
echo Test::$staticProperty; // выведет 'static'
// Выводим значение, обратившись к объекту класса:
echo $test::$staticProperty; // выведет 'static'
?>
Несколько объектов
Статические свойства принадлежат не какому-то объекту класса, а самому классу, хотя объекты класса и имеют доступ к этим свойствам.
На практике это означает то, что если у нас есть несколько объектов класса - статические свойства у них будут общие. То есть, если в одном объекте поменять значение статического свойства - изменения произойдут во всех объектах.
Давайте посмотрим на примере:
<?php
$test1 = new Test; // первый объект
$test2 = new Test; // второй объект
$test1::$staticProperty = 'static'; // запишем значение, используя первый объект
echo $test1::$staticProperty; // выведет 'static'
echo $test2::$staticProperty; // также выведет 'static'
?>
Статические методы и $this
Пусть у нас есть класс Test
с двумя
свойствами, статическим и обычным:
<?php
class Test
{
public static $staticProperty = 'static'; // статическое свойство
public $usualProperty = 'usual'; // обычное свойство
}
?>
Давайте выведем значения этих свойств в обычном
методе method
:
<?php
class Test
{
public static $staticProperty = 'static'; // статическое свойство
public $usualProperty = 'usual'; // обычное свойство
// Обычный метод:
public function method()
{
var_dump(self::$staticProperty); // выведет 'static'
var_dump($this->usualProperty); // выведет 'usual'
}
}
$test = new Test;
$test->method(); // обычный метод - вызываем через ->
?>
Из примера видно, что в обычном методе доступны
как статические, так и обычные свойства (и
методы). Пусть теперь наш метод method
будет статическим. В этом случае он сможет
обратиться с статическим методом и свойствам,
но к обычным - нет.
Почему: потому что внутри статических методов
недоступен $this
. Это происходит из-за
того, что статические методы могут вызываться
вне контекста объекта, просто обращаясь к
имени класса.
А ведь $this
внутри класса как раз-таки
ссылается на объект этого класса. Нет объекта
- $this
ни на что не ссылается. Убедимся
в этом: переделаем наш метод на статический
- теперь обращение к обычному свойству внутри
нашего метода будет выдавать ошибку:
<?php
class Test
{
public static $staticProperty = 'static'; // статическое свойство
public $usualProperty = 'usual'; // обычное свойство
// Переделали на статический метод:
public static function method()
{
var_dump(self::$staticProperty); // выведет 'static'
var_dump($this->usualProperty); // выдаст ошибку
}
}
$test = new Test;
$test::method(); // статический метод - вызываем через ::
?>
Применение
Пусть у нас есть вот такой класс User
:
<?php
class User
{
public $name;
public function __construct($name)
{
$this->name = $name;
}
}
?>
Давайте сделаем так, чтобы этот класс подсчитывал
количество своих объектов. Для этого сделаем
статическое свойство count
. Изначально
запишем в него значение 0
, а при создании
каждого нового объекта будем увеличивать
это значение на 1
.
Будем увеличивать значение нашего счетчика в конструкторе объекта:
<?php
class User
{
public static $count = 0; // счетчик объектов
public $name;
public function __construct($name)
{
$this->name = $name;
// Увеличиваем счетчик при создании объекта:
self::$count++;
}
}
?>
Проверим, что все работает:
<?php
$user1 = new User('user1'); // создаем первый объект класса
echo User::$count; //выведет 1
$user2 = new User('user2'); // создаем второй объект класса
echo User::$count; //выведет 2
?>
Не подсматривая в мой код реализуйте такой
же класс User
, подсчитывающий количество
своих объектов.
Улучшим наш код
Не очень хорошо то, что наш счетчик публичный
- его случайно можно изменить снаружи класса.
Давайте сделаем его доступным только для
чтения. Для этого объявим его приватным и
сделаем для него статический метод-геттер
getCount
:
<?php
class User
{
private static $count = 0;
public $name;
public function __construct($name)
{
$this->name = $name;
// Увеличиваем счетчик при создании объекта:
self::$count++;
}
// Метод, возвращающий значение счетчика:
public static function getCount()
{
// Выводим значение счетчика:
return self::$count;
}
}
?>
Проверим:
<?php
$user1 = new User('user1'); // создаем первый объект класса
echo User::getCount(); //выведет 1
$user2 = new User('user2'); // создаем второй объект класса
echo User::getCount(); //выведет 2
?>
Самостоятельно переделайте код вашего класса
User
в соответствии с теоретической
частью урока.