Форум программистов, компьютерный форум, киберфорум
PHP: ООП
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.81/100: Рейтинг темы: голосов - 100, средняя оценка - 4.81
 Аватар для Sined
9 / 7 / 3
Регистрация: 30.08.2008
Сообщений: 120

Как работают аксессоры __get и __set?

20.03.2010, 13:45. Показов 18945. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Недавно решил начать изучать PHP. Вообщем скачал книгу по ПХП и начал учить, дошел до аксессоров __get и __set и наткнулся на такую проблему. В книге написано следующее.

Аксессоры . Методы __set и __get
Неписаным правилам объектно-ориентированного программирования является использование только закрытых членов, доступ к которым осуществляется через открытые методы класса. Это позволяет скрыть внутреннюю реализацию класса, ограничить диапазон значений, которые можно присваивать члену, и сделать член доступным только для чтения. Неудобство заключается в том, что для каждого из членов приходится создавать
отдельный метод для чтения и присваивания нового значения, имена которых зачастую не совпадают с именами членов. Выходом из ситуации является использование свойств, обращение к которым выглядит точно так же, как к открытым членам класса. Для их реализации необходимо перегрузить специальные методы __get() и __set(), которые часто называют аксессорами. Метод __get() , предназначенный для чтения свойства, принимает единственный параметр, который служит ключом. Метод __set() позволяет присвоить свойству новое значение и принимает два параметра, первый из которых является ключом, а второй - значением свойства. В примере из листинга 1.19 при помощи метода __set() объекту присваиваются новые свойства, которые помещаются в массив $ this->arr, а перегруженный метод __get() позволяет извлечь их из массива.

Замечание
Следует обратить внимание, что методы __set() И __get() можно объявлять как закрытыми , так и открытыми .
Листинг 1.19. Использование методов __set() и __get()
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
class cls
{
         private $arr = array( ) ;
         private function __get($index)
         {
                  return $this->arr[$index];
         }
         private function __set($index, $value)
         {
                  $this->arr[$index]=$value;
         }
}
?>
Как видно из листинга 1.19, класс cls перехватывает все обращения к членам объекта и создает соответствующий элемент в закрытом массиве $arr. В листинге 1.20 демонстрируется, как обращение к члену $name приводит К созданию соответствующего элемента массива.

Листинг 1.20. Обращение к несуществующему эле менту $nаmе

Code
1
2
3
4
5
6
7
8
9
< ?php
require_once( "class.cls.php");
$ obj = new cls() ;
$ obj ->name = "Hello world!<br>" ;
echo $ obj ->name ;
echo "<pre>";
print_r($obj);
echo "</pre>";
?>
Результатом работы скрипта из листинга 1.20 являются следующие строки:

Code
1
2
3
4
5
6
7
8
9
Hello world!
 
cls Object
{
               [arr: private] => Array
               {
                            [name] => Hello world!
               }
}
Любая попытка присвоить члену значение приводит к созданию нового элемента закрытого массива $arr. Интересно, что когда член в классе уже существует, то аксессоры __set() и __get() перехватывают обращение к нему, если он является закрытым (имеет спецификатор доступа private), и не перехватывают, если он является открытым (public).

Замечание
Перегрузка обоих методов __get() и __set() не обязательна, допускается перегружать только один из них.
И у меня выдает следующие ошибки

PHP Warning: The magic method __get() must have public visibility and cannot be static in C:\Users\Denis\Desktop\a\classes\class.t est.php on line 13 PHP Stack trace: PHP 1. {main}() C:\Users\Denis\Desktop\a\index.php:0 PHP 2. __autoload() C:\Users\Denis\Desktop\a\index.php:0 PHP Warning: The magic method __set() must have public visibility and cannot be static in C:\Users\Denis\Desktop\a\classes\class.t est.php on line 18 PHP Stack trace: PHP 1. {main}() C:\Users\Denis\Desktop\a\index.php:0 PHP 2. __autoload() C:\Users\Denis\Desktop\a\index.php:0
я понял что выдает ошибку потому что аксессоры __get и __set не должны использоваться как private, но в замечани напсано что эти аксессоры могут использоваться как public так и private.

Это значит что если аксессор используется как private то его можно использовать только внутри реализации класса?????

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

и еще вопрос

как понять данное замечание?

Замечание
Перегрузка обоих методов __get() и __set() не обязательна, допускается перегружать только один из них.
Или это книга так написана непонятным языком или я чегото не понимаю
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
20.03.2010, 13:45
Ответы с готовыми решениями:

Как использовать аксессоры get/set
Есть код в классе Triangle.cs internal sealed class Triangle { public Point p0 { get { return p0; } private set { new Point(20,...

Аксессоры get, set
Здравствуйте. Вопрос, наверное, глупый, но все же. Я никак не могу понять для чего нужно использовать аксессоры get; set; пересмотрел много...

Как работают set mastera в Counter-Strike 1.6?
Кто знает как работают set mastera в counter strike 1.6??

10
 Аватар для Vovan-VE
13210 / 6599 / 1041
Регистрация: 10.01.2008
Сообщений: 15,069
20.03.2010, 14:55
Это не книга, а многобуков ( и, скорее всего, в кривом переводе). Читайте официальную документацию: Property overloading
1
6 / 6 / 1
Регистрация: 12.07.2009
Сообщений: 55
30.03.2010, 00:12
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
class cls
{
         private $переменная;
         private function __get($index)
         {
                  return $this->переменная;
         }
         private function __set($index, $value)
         {
                  $this->переменная=$value;
         }
}
?>
Как-то так)
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Или так 
class cls
{
         private $переменная1;
          private $переменная2;
         private function __get($index)
         {
                if(property_exists('cls',$index))
                 return $this->$index;
                else return 0;
         }
         private function __set($index, $value)
         {
                   if(property_exists('cls',$index))
                    $this->$index=$value;
         }
}
?>
0
 Аватар для Sined
9 / 7 / 3
Регистрация: 30.08.2008
Сообщений: 120
31.03.2010, 23:01  [ТС]
Цитата Сообщение от leroy Посмотреть сообщение
PHP
1
2
3
4
5
6
7
8
9
10
11
12
<?php class cls
 {
           private $переменная;
           private function __get($index)
           {
                         return $this->переменная;
           }
           private function __set($index, $value)
          {
                         $this->переменная=$value;
           }
 } ?>
...
ладно во втором примере я разобрался, по ходу аксессоры не должны быть приватными или статистическими, ибо получится ошибка(приведенная выше в моем п0сте), а как быть с первым примером?

как присвоить значение переменной через __set???

и вот еще прикол из первого примера:

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
class cls
{
         private $data;
         public function __get($index)
         {
                  return $this->переменная;
         }
         public function __set($index, $value)
         {
                  $this->переменная=$value;
         }
}
 
 
$a=new cls();
$a->tra_ta_ta=5;             //присваеваем переменной $data класса  cls значение 5
echo $a->tra_ta_ta2;        //выводим значение переменной $data класса  cls
?>
как он вооще работает? типа "пиши как хош"?
0
6 / 6 / 1
Регистрация: 12.07.2009
Сообщений: 55
02.04.2010, 11:34
Цитата Сообщение от Sined Посмотреть сообщение
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php
class cls
{
         private $data;
         public function __get($index)
         {
                  return $this->переменная;
         }
         public function __set($index, $value)
         {
                  $this->переменная=$value;
         }
}
 
 
$a=new cls();
$a->tra_ta_ta=5;             //присваеваем переменной $data класса  cls значение 5
echo $a->tra_ta_ta2;        //выводим значение переменной $data класса  cls
?>
как он вооще работает? типа "пиши как хош"?
Ты присваиваешь значение не $a->data а $a->переменная. вот где эта строчка $this->переменная=$value;
при этом учитывая что в твоем классе такого свойства как $переменная нет то оно создается при присваивании. при этом параметр $index метода __set ты вообще не используешь, если бы ты сделал так
PHP
1
2
3
4
public function __set($index, $value)
         {
                  $this->$index=$value;
         }
То при коде
PHP
1
$a->tra_ta_ta=5;
Создалось бы свойство tra_ta_ta у $a
И при следующем вызове echo $a->tra_ta_ta; метод __get уже не вызовится, потому как $a->tra_ta_ta существует
как присвоить значение переменной через __set???
Не совсем понятно что тебе не понятно))))
0
 Аватар для Sined
9 / 7 / 3
Регистрация: 30.08.2008
Сообщений: 120
02.04.2010, 23:30  [ТС]
я немного, прогнал, я смешал твой приведенай пример, со своим тестовским(просматривал как создается переменная) и написал твою "переменную" и свою переменную "data" и упустил эту ошибку, просто у тебя выше описано:

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
 class cls
{
         private $переменная;
         private function __get($index)
         {
                  return $this->переменная;
         }
         private function __set($index, $value)
         {
                  $this->переменная=$value;
         }
}
?>
почему я и начал спрашивать то что где используется параметр "index" в __get и __set
и при отладке я не вижу чтоб создавалась переменная, если ее создавать в мосиве, то я вижу что она создается а таким способом:

PHP
1
2
3
4
 public function __set($index, $value)
         {
                  $this->$index=$value;
         }
...я ее не вижу


а вообще все началось из-за той книги которую я описал в первом посте, там вооще непонятно как написано, описаны аксессоры с ключевым словом private, хотя аксессоры нельзя использовать с privatе, и вооще если чесно, чета меня он на стрем берет этот php уж очень за ним следить надо, нежели за C++ or С# or something else
0
 Аватар для Vovan-VE
13210 / 6599 / 1041
Регистрация: 10.01.2008
Сообщений: 15,069
03.04.2010, 08:43
На самом деле __get, __set, __call и т.п. вещи в PHP весьма сыроваты. В частности, __get и __set не сработают, как хотелось бы, в таком случае:
PHP
1
$foo->bar[2] = 'lol';
Добавлено через 2 минуты
Есть еще интерфейс ArrayAccess с походими симптомами:
PHP
1
2
3
4
5
6
7
8
9
class foo implements ArrayAccess {
    ...
}
 
$foo = new foo;
$foo['bar'] = 2; // ok
echo $foo['bar']; // ok
 
$foo['lol']['baz'] = 4; // не пашет, Notice
Добавлено через 2 минуты

Не по теме:

Опа, кейворд implements не подсвечивается :)

0
yurassic
06.05.2011, 16:51
2Leroy: ты пару раз сделал ошибку: при обращении к свойствам класса после стрелки -> доллар($) не ставится, иначе ошибка будет

2Vovan-VE: Книга эта русская и не в переводе. Но действительно, написано не всегда доходчиво (приходится додумывать), хотя структура очень грамотная..

Добавлено через 2 часа 26 минут
Кстати, у меня закрытые __get и __set нормально работают. Так что в книге все правильно написано. А в твоей ошибке вообще static указан, а не private... Но в чем трабл не знаю, ибо сам только начал изучать =)
6 / 6 / 1
Регистрация: 12.07.2009
Сообщений: 55
09.05.2011, 18:46
2Leroy: ты пару раз сделал ошибку: при обращении к свойствам класса после стрелки -> доллар($) не ставится, иначе ошибка будет
toyurassic:если Вы про это
PHP
1
2
3
4
public function __set($index, $value)
         {
                  $this->$index=$value;
         }
То тут ошибок нет, все верно
0
Особый статус
 Аватар для Proffessional
743 / 145 / 6
Регистрация: 16.07.2009
Сообщений: 2,185
Записей в блоге: 1
09.05.2011, 22:40
Sined, а может лучше http://php.su/lessons/?
0
Эксперт С++
 Аватар для CyBOSSeR
2348 / 1721 / 149
Регистрация: 06.03.2009
Сообщений: 3,675
09.05.2011, 22:53
Цитата Сообщение от Vovan-VE Посмотреть сообщение
В частности, __get и __set не сработают, как хотелось бы, в таком случае
Cработает, просто из __get нужно ссылку возвращать:
PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Foo {
  private $data = array();
 
  public function __set($name, $value) {
    $this->data[$name] = $value;
  }
 
  public function & __get($name) {
    return $this->data[$name];
  }
}
 
$foo = new Foo();
 
$foo->bar[2] = 'lol';
 
var_dump($foo->bar);
Результат: http://codepad.org/G9r4gJWu
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
09.05.2011, 22:53
Помогаю со студенческими работами здесь

Как работают свойства get set? F5 и F11 - один код, разные результаты!
В общем ситуация следующая - создаю два интовых свойства, и в get проверяю на равенство get {if (x == nuul) retern x++; retern x;} ...

функции аксессоры
помогите найти ошибку( #include &lt;stdio.h&gt; #include &lt;iostream.h&gt; #include &lt;string.h&gt; #include &lt;iomanip.h&gt; #include...

Свойства и Аксессоры
Возник такой вопрос по аксессорам: Пусть класс Sample содержит свойство Length с аксессорами get и set. Какие из следующих фрагментов...

inline аксессоры/мутаторы
собстно почему аксесоры/мутаторы некто не инлайнит ? поглядел пару опенсорсных проектов, везде вся реализация в .спп.

Аксессоры против методов
Доброго времени суток, раньше изучал С++, и при переходе на c# заметил что много используют аксессоры вместо привычных для меня методов,...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
PowerShell Snippets
iNNOKENTIY21 11.11.2025
Модуль PowerShell 5. 1+ : Snippets. psm1 У меня модуль расположен в пользовательской папке модулей, по умолчанию: \Documents\WindowsPowerShell\Modules\Snippets\ А в самом низу файла-профиля. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru