Профессиональная разработка Web-приложений.  
Боишься нашего дизайна?
Новости
PDF журнал
Участники проектa
Сотрудничество
Ссылки
Карта сайта
Комментарии
Комментарии к статье
Добавить комментарий
Обсудить на форуме
Информация об авторе
Оценка статьи

Объектно-ориентированное программирование, классы

Популярное объяснение понятий "класс" и "объект" и с чем их едят.

Мой путь к пониманию объектов шел слишком долго. Надо сказать, что закончился он чрезвычайно неожиданно - я прочел... мануал PHP 4. Где можно найти толковое описание, только не там, казалось бы... Правда, уже до этого я кое-что знал ("...объект, сочетающий в себе как совокупность данных, так и действий над ними." (с) Епанешников, "Программирование в среде Turbo Pascal 7.0"), но это уже детали.

Что же такое класс и объект. Сперва об объекте. Определение "...сочетающий в себе как совокупность данных, так и действий над ними" - вполне подходящее. Если говорить "приземленно", то объект в PHP - это переменная особого типа. В ней содержатся специально объявленные под-переменные и функции этого объекта (то, что объект содержит переменные и функции, в научной литературе называется инкапсуляцией). Функция is_object на эту переменную выдает true:

if (is_object($objectname)) {
  do_something();
  };

Обращение к под-переменной объекта производится следующим образом (название, конечно же неправильное, правильно "свойство объекта").

$objectname->property
print ($objectname->property);
//Вызов функции (метода) объекта:
$objectname->format_output($format);

Конечно же неудобно писать имя объекта и "стрелочку" ("->") перед нужной переменной, но это только поначалу. Зато потом можно сэкономить большой объем программного кода (и избежать лишней головной боли).

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

<?
class Public_Transport {
  var $capacity = 0;
  var $passengers = 0;
  var $stop = array();
  var $current_stop = 0;
  var $vehicle = "unknown";

  function say_stop () {
    echo $this->stop[$this->current_stop];
    if ($this->current_stop==sizeof($this->stop)-1)
      echo ". Конечная.";
    else
      echo " следующая - ", $this->stop[$this->current_stop+1];
    }

  function stop () {
    $this->passengers += intval(rand((-1*$this->passengers),100));
    if ($this->passengers > $this->capacity) {
      echo "Освобождаем двери!";
      $this->passengers = $this->capacity;
      };
    }

  function go () {
    $this->current_stop++;
    }
  }
?>

ВНИМАНИЕ! Закрывающая скобка класса должна быть без точки с запятой (""), как и все описания функций внутри описания класса.

Программа, работающая с классом Общественный_Транспорт будет выглядеть так:

<?
$bus = new Public_Transport;
$bus->capacity = 200;
$bus->vehicle = "Лиаз-767";
$bus->stop = array ("Торговый центр", "Поликлиника", "Институт теплофизики", 
"Вычислительный центр", "Институт ядерной физики", "Институт гидродинамики", 
"Морской проспект", "Дом ученых", "ул. Жемчужная", "Цветной проезд");

while ($bus->current_stop < sizeof($bus->stop)) {
  $bus->say_stop();
  $bus->stop();
  $bus->go();
  };
?>

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

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

<?
$a = "bukva a";
$b = "bukva b";
$c = "a";
echo $$c;
?>

Такой код выведет "bukva a". И то же самое можно делать с объектами и их свойствами:

<?
class someclass1 {
  var $a = 1;
  var $b = 2;
  var $c = 3;
  }

class someclass2 {
  var $a = 4;
  var $b = 5;
  var $c = 6;
  }

$d = new someclass1;
$e = new someclass2;

$f = "d";
$g = "c";

echo ${$f}->{$g};
?>

(такой код выдаст "3")

То же касается и динамических имен функций.

В руководстве по PHP4 написано подробнее о динамичесих именах переменных и изменяемых именах функций.

И на прощанье вот что. В начале года мне надо было написать скрипт для рассылки новостей и прайс-листов подписчикам. Зашел я на сайт PHP и заглянул в мануал по функции mail(), чтобы найти что-нибудь про аттачмент. В комментариях к функции я нашел то, что искал - класс для вложения файла в письмо. За восемь месяцев туда накидали много ссылок на такие классы, а в феврале он был единственный - CMailFile. Так вот, как они делают - делать не надо (я тогда в классах разбирался смутно, и просто вырезал функции, несколько упростив код). Процитирую заголовки функций:

class CMailFile {
  var $subject;
  var $addr_to;
  var $text_body;
  var $text_encoded;
  var $mime_headers;
  var $mime_boundary = "--==================_846811060==_";
  var $smtp_headers;

  function CMailFile($subject,$to,$from,$msg,$filename,
		$mimetype = "application/octet-stream", $mime_filename = false) {
/* если функция имеет то же имя, что и класс, то это будет конструктор класса */

  function attach_file($filename,$mimetype,$mime_filename) {
/* Вот это не понимаю! attach_file вызывается из функции CMailFile - зачем? 
Только для красоты. А так - можно было этот кусок кода вставить прямо в главную 
функцию, раз уж решено сделать единовременный вызов функции. Далее идут несколько 
функций того же назначения и характера. */
  function encode_file($sourcefile) {
  function sendfile() {
  function write_mimeheaders($filename, $mime_filename) {
  function write_smtpheaders($addr_from) {

  }

/* А вот пример использования класса. */ 

// usage - mimetype example "image/gif"
// $mailfile = new CMailFile($subject,$sendto,$replyto,$message,$filename,$mimetype);
// $mailfile->sendfile();

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

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


For comment register here
   2001-01-02 10:16
есть ли еще где-нибудь информация по классам на русском кроме переведенного мануала ?

   Unknown 2001-01-02 11:09
Например, <a href=http://www.webclub.ru/materials/php3/>;здесь</a>. Но это описание PHP3, так что оно весьма отстает от жизни.

   Unknown 2001-01-04 08:16
Например, <a href=http://ru.php.net/manual/oop.php3>;мануал по PHP</a> :) Ведь там ясно написано: Classes and Objectt

   2001-01-04 15:54
Я думаю, что автор класса
просто отдал дань традиции написания классов, когда
считалось хорошим тоном разделять конструкотры и метода вплоть до того, что
для каждой публичной переменной существовала функция для получения ее значения и
функция для занесения в нее.
А так же исключительно для читаемоти кода удобнее разделять функции между собой, причем это касается не только классов.

   Unknown 2001-01-04 16:47
Да, возможно, это так и есть.

   2001-01-30 04:46
Здравствуйте!
есть такой вопрос.
если сможете помогите. Очень надо.
есть
class A {
var a;
var b;
.....
function pr(){
echo "a";
}
}
class B extends A{

function pr(){
echo "b";
}
}
Так вот если создадим объкт класса B
и напишем b->pr(); то напечатается b, но надо
чтобы вызвалась сначала функция из класса A а потом из класса B.
т.е.

class B extends A {
function pr(){
a = convert(b)//вот такую фунцию необходимо написать
a->pr();
echo "b";
}
}
я конечно понимаю что задание не имеет смысла и что на php4
можно просто написать a::pr();
но если сможете пожалуйста ответьте
можно на почту.

   2001-02-21 13:06
Господа! Проверяйте грамматику перед опубликованием на сайте странички, а не после того, как вас об этом попросят.
На этой странице после формы отзыва есть слова:
"Нажимая эту кнопку вы соглашаетесь со следующим:
1)ваш отзыв - публичное высказывание, всю ответственность за него несете вы."
Насколько я знаю, после деепричастного оборота <нажимая эту кнопку> должна следовать ЗАПЯТАЯ!
Уважаемые! "Ваша статья - публичное высказывание. Вся ответственность за безграмотность и опечатки возлагается тяжелым бременем стыда на русскоязычных людей".

С наилучшими пожеланиями.

   Unknown 2001-02-21 13:59
Мда... люблю критиковать других на отсутствие запятых, лишние мягкие знаки... Сейчас исправлю. Но вообще лучше такое отправлять приватом.

   2001-04-09 09:33
1. Твое непонятие - очень странно... Потому что, в следующей статье ты ответил на свой же вопрос...
Подсказка, ООП - прежде всего для удобства разработки, а дело десятое скорость(Хотя ты можешь считать, что это мдленне должно быть, но компиляторы умеют проводить оптимизацию)...

1.1. Оформлять или не оформлять как класс - это зависит от того как ты собираешься писать... Если с ОО подоходом - то это класс; если без, то пофигу как его делать... даже лучше вообще классом не оформлять.

Так что изменять прямо свояства класса - это уже усеченный ОО подход. :)

2. Класс - это закоченное описание какой-либо сущности включая все нужне действия и свойства.
Объект - это конкретная сущность... Так вернее. Класс - первичнее, чем объект. Хотя бы потому, что один объект может представлять сразу несколько классов((из-за наследования)треугольник -> плоская фигура -> фигура) и работать с ним можно тоже исходя из этого(то есть когда хочу - это треугольник, а когда подругому хочу - это плоская фигура), а вот Класс - это все-таки законечнное описание сущности(плоская фигура - это конечно тоже фигура, но она обязательно(!) имеет свои собственные свойства и возможные действия и если их выбросить - то это уже будет все-таки класс фигура, а не класс плоская фигура).

Вообщем типа того... :)

2. attach_file используется в конструторе потому, что при создании письма ты можешь задать аттачмент... Также, ты можешь задать 2 или 3 аттачмента к письму... но уже без констурктора. Поэтому, зачем плодить attach_file в разных местах, когда удобнее сделать его одним.

3. Инкапсуляция - это сокрытие реализации от конечного пользователя. И это не дань традиции, а насущная необходимость. Класс разрабатывается под определенные задачи, которые он должен решать, поэтому дело десятое как именно я храню внутренние переменные класса. В идеале, к ним не должно быть доступа вообще, даже через функции типа GetProperty. Если для задачи нужно, чтобы тебе возвращали какое-то свойство класса - делай для этого паблик метод. НО!!! Заметь, совершенно не факт, что в классе это свойство действительно есть. Простой пример: класс треугольник - можно задать тремя точками, двумя векторами, вектором и двумя углами... Причем, вектор,точка и угол - могут быть в принципе тоже объектами. Если для задачи нужно иметь получение всех точек треугольник - делаем этот метод... А от замены внутреннго представления твоя программа соверщенно не зависит. Поэтому, если в следующей версии класса, который вообще говоря, может рапространятся уже в скомпилированном виде, заменят внутреннюю реализацию для увеличения скорости, уменьшения памяти и т.п.- у тебя программа будет нормально работать.

P.P.S. Если чего - пишиет на мыло... Пообщеамся.

   2001-07-30 12:17
Вот такой код
class table {
var $table_tag;
var $td_tag;
var $tr_tag;
......
var $host;
var $user;
var $passwd;
var $db;
........
//надо написать класс который показывает любую таблицу из любой БД в странице
//и представьте что таблица очень большая (очень много строк)
//и мне нужно изобразить, например по 4 строк на странице, получается чтото в этом роде
// +----+-----------+----------+
// |id | name | phone |
// +---+-----------+----------+
// | 1 | Ivanov | 53456245 |
// +---+-----------+----------+
// | 2 | Petrov | 87987932 |
// +---+-----------+----------+
// Другие страницы: <<Previous 1, 2, 3, 4, ..., Nex>>
//Так вот, как мне передвигаться с одной странице на другой
//я пробовал <a href=file.php?page=$no_page>$no_page</a>
//т.е. $no_page номер страницы к которой нужно идти, но не получается,
// Если вы сталкивались раньше с токой проблемой или знете как это делется, прошу вас подскажите мне,
// Спасибо.
}

   2002-03-19 11:03
Я раньше работал с Дельфи... долго мучился над процедурным программированием ПХП... после этой статьи я опять вернулся к жизни... большое спасибо...

Популярное объяснение понятий

 
 
 
    © 1997-2008 PHPClubTeam
[]