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

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

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

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

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

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

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

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

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

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

Начать->

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

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

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

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

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

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

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

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

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

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

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

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


Классы и объекты в PHP, определение свойств в классе

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

Первый класс

Классы часто описывают с помощью объектов. Это очень интересно, потому что объекты часто описывают с помощью классов.

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

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

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

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


class ShopProduct {
    // тело класса
}

Класс ShopProduct из этого примера - уже полноправный класс, хотя пока и не слишком полезный. Но тем не менее мы сделали нечто очень важное. Мы определили тип, т.е. создали категорию данных, которые можем использовать в своих сценариях. Важность этого станет для вас очевидной по мере дальнейшего чтения.

Первые несколько объектов

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

Мы будем использовать класс ShopProduct как форму для создания объектов типа ShopProduct. Для этого нам нужен оператор new. Он используется совместно с именем класса следующим образом.


$product1 = new ShopProduct();
$product2 = new ShopProduct();

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

Итак, мы использовали класс ShopProduct как шаблон для создания двух объектов типа ShopProduct. Хотя функционально они идентичны (т.е. пусты), $product1 и $product2 - это два разных объекта одного типа, созданных с помощью одного класса.

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

Тип создаваемых объектов определяется формой отливки. Утки выглядят одинаковыми во всех отношениях, но все же это разные предметы.

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

Каждому объекту, создаваемому в PHP-сценарии также присваивается уникальный идентификатор (он уникален на время жизни объекта), т.е. PHP повторно использует идентификаторы, даже в пределах одного и того же процесса (т.е. запуска сценария). Это можно продемонстрировать, выведя на печать объекты $product1 и $product2.


var_dump($product1);
var_dump($product2);

После выполнения этих функций будут выведены следующие данные.


object(ShopProduct)#1 (0) {
}
object(ShopProduct)#2 (0) {
}

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

Чтобы сделать эти объекты более интересными, мы должны немного изменить определение класса ShopProduct, добавив в него специальные поля данных, называемые свойствами (properties).


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

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

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

На заметку*
Область видимости (scope) определяет контекст функции или класса, в которой можно пользоваться данной переменной (или методом, о чем мы поговорим далее). Так переменная, определенная внутри тела функции, имеет локальную область видимости, а переменная, определенная за пределами функции, - глобальную область видимости.

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

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

К каким переменным можно получать доступ и из какого контекста, и определяют ключевые слова public, protected или private, как мы вскоре увидим.

К этим ключевым словам и вопросу видимости мы вернемся несколько позже. А сейчас давайте определим некоторые свойства с помощью ключевого слова public.


class ShopProduct {
    public $title               = "default product";
    public $producerMainName    = "main name";
    public $producerFirstName   = "first name";
    public $price               = 0;
}

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

А ключевое слово public, присутствующее в объявлении каждого свойства, обеспечит доступ к этому свойству извне контекста объекта.

К переменным свойств можно обращаться с помощью символов "->", указав имя объектной переменной и имя свойства.


$product1 = new ShopProduct();
print "{$product1->title}";

В результате будет выведено следующее.


default product

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


$product1 = new ShopProduct();
$product2 = new ShopProduct();

$product1->title = "Собачье сердце";
$product2->title = "Ревизор";

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

Это означает, что при таком предположении код, использующий данный класс, сможет работать с любыми объектами типа ShopProduct. Но поскольку мы можем легко переопределить это свойство, значение $title может меняться от одного объекта к другому.

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

На самом деле в PHP необязательно объявлять все свойства в классе. Свойства можно динамически добавлять к объекту следующим образом.


$product1->arbitraryAddition = "Дополнительный параметр";

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

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

Если в классе ShopProduct определяется свойство $title, то любой код, который работает с объектами тимпа ShopProduct, может исходить из предположения, что свойство $title определено. Но подобной гарантии относительно свойств, определенных динамически, не существует.

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


$product1 = new ShopProduct();

$product1->title = "Собачье сердце";
$product1->producerMainName  = "Булгаков";
$product1->producerFirstName = "Михаил";
$product1->price = 5.99;

Здесь мы снова используем класс ShopProduct, переопределяя одно за другим все стандартные значения его свойств, пока не определим всю информацию о товаре. А теперь, когда мы определили некоторые данные, можно к ним обратиться.


print "Автор: {$product1->producerFirstName} "
             ."{$product1->producerMainName}\n";

В результате на выходе получим следующее.


Автор: Михаил Булгаков

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


$product1->producerMainName = "Булгаков";

как


$product1->producerSecondName = "Булгаков";

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

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

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

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


print "Автор: {$product1->producerFirstName} "
             ."{$product1->producerMainName}\n";

И было бы прекрасно, если бы объект делал это за нас.

Все эти проблемы можно решить, если снабдить объект ShopProduct собственным набором функций, которые можно использовать для выполнения операций над данными внутри контекста объекта.

Читайте об этом в статье Работа с методами в объектно-ориентированном программировании на PHP".

P.S. Хотите двигаться дальше в освоении PHP и ООП? Обратите внимание на премиум-уроки по различным аспектам сайтостроения, включая программирование на PHP, а также на бесплатный курс по созданию своей CMS-системы на PHP с нуля с использованием ООП:

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Наверх