Reg.ru: домены и хостинг

Крупнейший регистратор и хостинг-провайдер в России.

Более 2 миллионов доменных имен на обслуживании.

Продвижение, почта для домена, решения для бизнеса.

Более 700 тыс. клиентов по всему миру уже сделали свой выбор.

Перейти на сайт->

Бесплатный Курс "Практика HTML5 и CSS3"

Освойте бесплатно пошаговый видеокурс

по основам адаптивной верстки

на HTML5 и CSS3 с полного нуля.

Начать->

Фреймворк Bootstrap: быстрая адаптивная вёрстка

Пошаговый видеокурс по основам адаптивной верстки в фреймворке Bootstrap.

Научитесь верстать просто, быстро и качественно, используя мощный и практичный инструмент.

Верстайте на заказ и получайте деньги.

Получить в подарок->

Бесплатный курс "Сайт на WordPress"

Хотите освоить CMS WordPress?

Получите уроки по дизайну и верстке сайта на WordPress.

Научитесь работать с темами и нарезать макет.

Бесплатный видеокурс по рисованию дизайна сайта, его верстке и установке на CMS WordPress!

Получить в подарок->

*Наведите курсор мыши для приостановки прокрутки.


Статические методы и свойства в PHP

Перед изучением данной статьи вы можете прочитать предыдущую статью из этой серии - "Управление доступом к классам: спецификаторы доступа public, private и protected".

В предыдущих материалах мы освоили основные возможности объектно-ориентированного программирования в PHP и сейчас переходим к изучению более сложных и интересных аспектов.

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

Отсюда следовал вывод, что что в объектно-ориентированном программировании реальная работа выполняется с помощью экземпляров классов. А классы в конечном счете - это просто шаблоны для создания объектов.

Но на самом деле не все так просто. Мы можем получать доступ и к методам, и к свойствам в контексте класса, а не объекта. Такие методы и свойства называются "статическими" и должны быть объявлены с помощью ключевого слова static.


class StaticExample {
    static public $aNum = 0;

    static public function sayHello() {
        print "Привет!";
    }
}

Статические методы - это функции, используемые в контексте класса. Они сами не могут получать доступ ни к каким обычным свойствам класса, потому что такие свойства принадлежат объектам.

Однако из статических методов, как вы уже наверное догадались, можно обращаться к статическим свойствам. И если вы измените статическое свойство, то все экземпляры этого класса смогут получить доступ к новому значению.

Поскольку доступ к статическому элементу осуществляется через класс, а не через экземпляр объекта, нам не нужна переменная, которая ссылается на объект. Вместо этого используется имя класса, после которого указывается два двоеточия "::".


print StaticExample::$aNum;
StaticExample::sayHello();

С этим синтаксисом вы уже должны быть знакомы по основам ООП в PHP. Мы использовали конструкцию "::" в сочетании с ключевым словом parent для того, чтобы получить доступ к переопределенному методу родительского класса.

Сейчас, как и тогда, мы обращаемся к классу, а не к данным, содержащимся в объекте. В коде класса можно использовать ключевое слово parent для того, чтобы получить доступ к суперклассу, не используя имя класса.

Чтобы получить доступ к статическому методу или свойству из того же самого класса (а не из дочернего класса), мы будем использовать ключевое слово self.

Ключевое слово self используется для обращения к текущему классу, а псевдопеременная $this - к текущему объекту. Поэтому из-за пределов класса StaticExample мы обращаемся к свойству $aNum с помощью имени его класса.


StaticExample::$aNum;

А внутри класса StaticExample можно использовать ключевое слово self.


class StaticExample {
    static public $aNum = 0;

    static public function sayHello() {
        self::$aNum++;
        print "Привет! (" . self::$aNum . ")\n";
    }
}

Обратите внимание: кроме случаев обращения к переопределенному методу родительского класса, конструкция "::" должна всегда использоваться только для доступа к статическим методам или свойствам.

По определению статические методы не вызываются в контексте объекта. По этой причине статические методы и свойства часто называют переменными и свойствами класса. Как следствие, нельзя использовать псевдопеременную $this внутри статического метода.

А зачем вообще использовать статический метод или свойство?

Вот мы и дошли до самого важного вопроса. Дело в том, что у статических элементов есть ряд полезных характеристик.

Во-первых, они доступны из любой точки сценария (при условии, что у вас есть доступ к классу). Это означает, что вы можете обращаться к функциям не передавая экземпляр класса от одного объекта другому или, что еще хуже, сохраняя экземпляр объекта в глобальной переменной.

Во-вторых, статическое свойство доступно каждому экземпляру объекта этого класса. Поэтому можно определить значения, которые должны быть доступны всем объектам данного типа.

И, наконец, в-третьих, сам факт, что не нужно иметь экземпляр класса для доступа к его статическому свойству или методу, позволит избежать создания экземпляров объектов исключительно ради вызова простой функции.

Чтобы продемонстрировать это, давайте создадим статический метод для класса ShopProduct, который будет автоматически создавать экземпляры объектов ShopProduct. C помощью SQLite определим таблицу products следующим образом:


CREATE TABLE products (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    type TEXT,
                    firstname TEXT,
                    mainname TEXT,
                    title TEXT,
                    price float,
                    numpages int,
                    playlength int,
                    discount int
					)

Теперь создадим метод getInstance(), которому передается идентификатор строки и объект типа PDO. Они будут использоваться для извлечения строки из таблицы базы данных, на основании которой затем формируется объект типа ShopProduct, возвращаемый в вызывающую программу.

Мы можем добавить эти методы к классу ShopProduct, который был создан нам в более ранних материалах. Как вы, наверное, знаете, PDO расшифровывается как PHP Data Object (объекты данных PHP). Класс PDO обеспечивает универсальный интерфейс для различных приложений баз данных.


// Класс ShopProduct
private $id = 0;

public function setID( $id ) {
        $this->id = $id;
    }

// ...

public static function getInstance( $id, PDO $pdo ) {
        $stmt = $pdo->prepare("select * from products where id=?");
	$result = $stmt->execute(array($id));
        $row = $stmt->fetch( );
        if ( empty( $row ) ) { return null; }

        if ( $row['type'] == "book" ) {
            $product = new BookProduct( 
                                    $row['title'], 
                                    $row['firstname'], $row['mainname'], 
                                    $row['price'], $row['numpages'] ); 
        } else if ( $row['type'] == "cd" ) {
            $product = new CdProduct(
                                    $row['title'], 
                                    $row['firstname'], $row['mainname'], 
                                    $row['price'], $row['playlength'] ); 
        } else {
            $product = new ShopProduct(     
                                    $row['title'], 
                                    $row['firstname'], $row['mainname'], 
                                    $row['price'] ); 
        }
        $product->setId(            $row['id'] );
        $product->setDiscount(      $row['discount'] );
        return $product;
    }
// ...

Как видите, метод getInstance() возвращает объект типа ShopProduct, причем он достаточно "умен" для того, чтобы на основании значения поля type создавать объект с нужными характеристиками.

Я специально опустил код обработки ошибок, чтобы пример был по возможности лаконичным. Например, в реально работающей версии этого кода нам нельзя быть слишком доверчивыми и предполагать, что переданный PDO-объект был корректно проинициализирован и подключен к требуемой базе данных.

На самом деле нам, вероятно, следует заключить PDO-объект в класс, который гарантирует такое поведение. К этому вопросу мы еще вернемся в одном из будущих материалов.

Метод getInstance() более полезен в контексте класса, чем в контексте объекта. Он позволяет легко преобразовать данные, находящиеся в базе данных, в объект, причем для этого нам не нужно иметь отдельный экземпляр объекта типа ShopProduct.

В этом методе не используются никакие методы или свойства, требующие отдельного экземпляра объекта, поэтому нет никакой причины, чтобы не объявить его статическим. Тогда, имея корректный PDO-объект, мы можем вызвать данный метод из любого места приложения.


$dsn = "sqlite://home/bob/projects/products.db";
$pdo = new PDO ($dsn, null, null);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$obj = ShopProduct::getInstance(1, $pdo);

Подобные методы работают как "фабрики", поскольку они берут "сырые" материалы (например, данные, полученные из строки базы данных или файла конфигурации) и используют их для создания объектов.

Термин "фабрика" относится к коду, предназначенному для создания экземпляров объектов. С примерами подобных "фабрик" мы еще встретимся с вами дальше.


Постоянные свойства

Некоторые свойства не должны изменяться. Например, такие элементы, как коды ошибок или коды состояния программы, задаются обычно вручную в классах. Хотя они должны быть общедоступными и статическими, клиентский код не должен иметь возможность изменять их.

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

В отличие от обычных свойств, перед именем постоянного свойства не ставится знак доллара. По принятому соглашению им часто назначают имена, состоящие только из прописных букв, как в следующем примере:


class ShopProduct {
    const AVAILABLE      = 0;
    const OUT_OF_STOCK   = 1;
// ...

Постоянные свойства могут содержать только значения, относящиеся к элементарному типу. Константе нельзя присвоить объект.

Как и к статическим свойствам, доступ к постоянным свойствам осуществляется через класс, а не через экземпляр объекта. Подобно тому как константа определяется без знака доллара, при обращении к ней также не требуется использовать никакой символ впереди.


print ShopProduct::AVAILABLE;

Попытка присвоить константе значение после того, как она была объявлена, приведет к ошибке на этапе синтаксического анализа..

Константы следует использовать, когда свойство должно быть доступным для всех экземпляров класса и когда значение свойства должно быть фиксированным и неизменным.

На этом данную статью я завершаю, а в следующей речь пойдет про абстрактные классы и интерфейсы в PHP.

Понравился материал и хотите отблагодарить?
Просто поделитесь с друзьями и коллегами!


Смотрите также:

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

PHP: Получение информации об объекте или классе, методах, свойствах и наследовании

CodeIgniter: жив или мертв?

CodeIgniter: жив или мертв?

Функции обратного вызова, анонимные функции и механизм замыканий

Функции обратного вызова, анонимные функции и механизм замыканий

Применение функции к каждому элементу массива

Применение функции к каждому элементу массива

Слияние массивов. Преобразование массива в строку

Слияние массивов. Преобразование массива в строку

Деструктор и копирование объектов с помощью метода __clone()

Деструктор и копирование объектов с помощью метода __clone()

Эволюция веб-разработчика или Почему фреймворк - это хорошо?

Эволюция веб-разработчика или Почему фреймворк - это хорошо?

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

Магические методы в PHP или методы-перехватчики (сеттеры, геттеры и др.)

PHP: Удаление элементов массива

PHP: Удаление элементов массива

Ключевое слово final (завершенные классы и методы в PHP)

Ключевое слово final (завершенные классы и методы в PHP)

50 классных сервисов, программ и сайтов для веб-разработчиков

50 классных сервисов, программ и сайтов для веб-разработчиков

Наверх