Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Баг в ООП?

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Без описания
Goshik
Отправлено: 27 Июля, 2010 - 16:45:15
Post Id



Новичок


Покинул форум
Сообщений всего: 28
Дата рег-ции: Сент. 2008  


Помог: 0 раз(а)




Имеем код:


PHP:
скопировать код в буфер обмена
  1. class A{
  2.  
  3.   const C = 100500;
  4.                
  5.   function C(){return self::C;}
  6.                
  7. }
  8.  
  9.        
  10.        
  11. class B extends A{
  12.        
  13.   const C = 100600;
  14.                
  15.   function __construct(){echo self::C();}
  16.        
  17. }
  18.  
  19.        
  20. new B();


Вопрос: Какого выводится 100500, а не 100600?
 
 Top
Arch-Web
Отправлено: 27 Июля, 2010 - 16:49:34
Post Id



Частый гость


Покинул форум
Сообщений всего: 177
Дата рег-ции: Июль 2010  
Откуда: Ukraine::Kiev


Помог: 1 раз(а)




ну потому что функция С() находится в классе A
 
 Top
Goshik
Отправлено: 27 Июля, 2010 - 16:54:26
Post Id



Новичок


Покинул форум
Сообщений всего: 28
Дата рег-ции: Сент. 2008  


Помог: 0 раз(а)




Да, но вызывается метод ЦЭ() из контекста класса БЭ, поэтому по идее должён возвращать переопределённую константу ЦЭ.
 
 Top
Arch-Web
Отправлено: 27 Июля, 2010 - 16:58:24
Post Id



Частый гость


Покинул форум
Сообщений всего: 177
Дата рег-ции: Июль 2010  
Откуда: Ukraine::Kiev


Помог: 1 раз(а)




Goshik ну она только вызывается ,у вас два класса и с класса С вы можете использувать все что в классе А ,а так как вы используете функцию с класса А то она и возвращает вам то что в A::C
 
 Top
unded
Отправлено: 27 Июля, 2010 - 17:30:21
Post Id


Новичок


Покинул форум
Сообщений всего: 43
Дата рег-ции: Март 2010  


Помог: 0 раз(а)




Попробуй так :
PHP:
скопировать код в буфер обмена
  1.  
  2. class A{
  3.  
  4.   const C = 100500;
  5.                
  6.   function C(){return self::C;}
  7.                
  8. }
  9.  
  10.        
  11.        
  12. class B extends A{
  13.        
  14.   const C = 100600;
  15.                
  16.   function __construct(){echo parent::C();}
  17.        
  18. }
  19.  
  20.        
  21. new B();
  22.  
 
 Top
Goshik
Отправлено: 27 Июля, 2010 - 17:48:53
Post Id



Новичок


Покинул форум
Сообщений всего: 28
Дата рег-ции: Сент. 2008  


Помог: 0 раз(а)




2unded
Ты меня неправильно понял. Я хочу добиться эффекта прототивоположного тому что ты предлагаешь.

2Arch-Web На сколько я знаю при наследовании, в классе наследнике создаются свои методы. И они нифига не должны вызываться из класа родителя. Для этого есть ключевое слово parent.

Приведу ещё один пример:

PHP:
скопировать код в буфер обмена
  1.  
  2. class A{
  3.  
  4.   protected $C = 100500;
  5.        
  6.   function C(){return $this->C;}
  7.                
  8. }
  9.  
  10.        
  11.        
  12. class B extends A{
  13.        
  14.   protected $C = 100600;
  15.                
  16.   function __construct(){echo $this->C();}
  17.        
  18. }
  19.  
  20.  
  21. new B();
  22.  



Здесь всё ОК, выводится 100600 как и следовало ожидать. Почему эта фича не работает с константами и статическими полями, йух его знает. Возможно дело в разнице "->" и "::". Или просто я туплю?
 
 Top
Мелкий Супермодератор
Отправлено: 27 Июля, 2010 - 18:22:47
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




А может именно от того, что это константа и дочерний класс её просто не переопределяет?


-----
PostgreSQL DBA
 
 Top
Arch-Web
Отправлено: 27 Июля, 2010 - 18:24:29
Post Id



Частый гость


Покинул форум
Сообщений всего: 177
Дата рег-ции: Июль 2010  
Откуда: Ukraine::Kiev


Помог: 1 раз(а)




Мелкий скорей всего так и есть ,т.к константу нельзя переписать
 
 Top
Goshik
Отправлено: 27 Июля, 2010 - 18:37:45
Post Id



Новичок


Покинул форум
Сообщений всего: 28
Дата рег-ции: Сент. 2008  


Помог: 0 раз(а)




>Мелкий скорей всего так и есть ,т.к константу нельзя переписать
Авотфиг. Если написать в конструкторе класса БЭ echo self::C, то тогда выведется 100600, т.е. константа переопределяется. Также напоминаю что со статическими полями та же фигня.

Добавлено:

Есть подозрение, что косяк вот в чём:
self - это константа, которая заменяется на имя класса в котором обЪявлен метод (в нашем случае это A).
$this - это переменная в которой хранится ссылка на создаваемый обЪект. В нашем случае обЪект БЭ.

Вот если бы к константам можно было к константам через зыс обращаться...

(Отредактировано автором: 27 Июля, 2010 - 18:43:35)

 
 Top
JustUserR
Отправлено: 30 Июля, 2010 - 02:17:36
Post Id



Активный участник


Покинул форум
Сообщений всего: 8715
Дата рег-ции: Июнь 2009  


Помог: 17 раз(а)




Goshik Ваш вопрос является достаточно интересным и для получения полного ответа на него - необходимо подробно разобрать каким образом поступает PHP-интерпретатор при выполнении данного участка кода - в частности рассмотреть области видимости и пространства имен объектов а также динамическое связывание во время выполнения
Важно понимать что несмотря на то что PHP напрямую реализует ООП-концепции но он является динамически языком - и поэтому реальные программные элементы классов имеют свою область видимости и свое время разыменовывания и подстановки значения переменных то есть динамического связывания И даже если некоторая функция используестся в наследуемом классе - то часть контекста она берет из того участка программного кода где она реально определена Такое поведение берет свое начало из того что в PHP иногда объекты первого и второго рода смешиваются между собой - с одной стороны в PHP 5.2 функция не является объектом первого рода и может определеяться только один раз и притом статически - но в то же время возможно условное определение функций или наличие вложенных функций что является проявление повеления объекта первого рода Аналогичная ситуация проявляется и при работе с ООП - с одной стороне методы базовых классов и классов-наследников проявляются в контексте текущего экземпляра и сам класс является только шаблоном - но с другой стороны элементы класса могут работать как отдельный программный код
Рассмотрим различные варианты обработки приведенного PHP-кода интерпретатором К примеру для ускорения процесса обработки интерпретатор может производить предварительную замену значений-констант в соответствии с пространством имен в котором они находятся - в таком случае приведенная функция к моменту выполнения уже будет содержать конструкцию вывода заданной константы - и соответственно везде где данная функция будет использоваться она будет возвращать одно и то же значений В принципе такой подход является оправданным - ведь в PHP функции по умолчанию работают с локальными переменными вне зависимости от того из какого контекста они вызывались - и соответственно в отсутсвии оператора глобализации global она должна сохранять это значений С классами ситуация обстоит почти также причем имя класса является именем пространства имен а оператор :: используется для расширения области видимости - то есть для обычного метода внутри класса локальными являются его внутренние переменные и поля класса доступные через операцию расширения области видимости С другой стороны с точки зрения обычного ООП для метода класса должны быть доступны в качестве локальный переменных поля конкретного экземпляра - в этом случае они привязаны уже не к контексту в котором располагается код метода а к контексту в котором они вызываются через соответствующий экземпляр Таким образом получается что метод класса работает с двумя типами переменных из разных контекстов - которые тем не менее являются локальными относительно него и обращение к которым осуществляется через ключевое слово self При этом ввиду различной природы данных переменных и контекстов к которым они принадлежат сооответствующее динамическое связывание происходит также в различое время - из-за чего и возникает указанная вами особенность
Goshik пишет:
Также напоминаю что со статическими полями та же фигня
Статические поля по сути являются обычными переменными находящимися в определенном пространстве имен доступ к которому осуществляется через имя класса и оператор расширения области видимости - и соответственно при наследовании классов и создании экземпляров они остаются неизменными и привязанными к самому определению класса Поля констант таким образом можно считать статическими полями - доступными для инициализации только один раз
В PHP существуют достаточно эффективные средства которые возволяет управлять указанной схемой работы - пакет runkit http://www.php.su/functions/?cat=runkit позволяет осуществлять динамические манипуляции с элементами классов и обычными функциями С помощью использования данных функций а также eval по необходимости можно добиться осуществление связывание в нужный момент времени - с переключением на соответствущим правильный контекст - при этом перерасчет кода метода должен происходить в связи с требуемым классом


-----
Сделать можно все что угодно - нужно только старание, терпение и хороший поисковик Улыбка
Безлимитный web-хостинг от 15 рублей за 40 МБ дискового пространства - http://ihost[dot]oks71[dot]ru/
 
 Top
like_you
Отправлено: 30 Декабря, 2010 - 19:30:17
Post Id


Гость


Покинул форум
Сообщений всего: 82
Дата рег-ции: Июнь 2010  
Откуда: Харківська обл. с. Криштопівка


Помог: 0 раз(а)




Или я чего то недопонял в обсуждаемом вопросе или просто не все видят такую маленькую деталь как скопки при вызове self::C().
Если требуется переопределить константу, то просто нужно вызвать self::C в дочернем классе:
PHP:
скопировать код в буфер обмена
  1. <?PHP
  2. class A{
  3.    const C = 100500;
  4.   function C(){return self::C;}
  5. }
  6.      
  7. class B extends A{
  8.   const C = 100600;
  9.   function __construct(){echo self::C;}
  10. }
  11. new B();
  12. ?>

Выводит, как и хотели 100600 - константа очевидно переопределилась.
(Добавление)
*точнее не переопределить, а прочитать переопределённую константу.


-----
Створюю український хабр
 
 Top
OrmaJever Модератор
Отправлено: 30 Декабря, 2010 - 19:58:36
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




Goshik пишет:
Вопрос: Какого выводится 100500, а не 100600?

Потому что а класе B нету метода С()
(Добавление)
Goshik пишет:
Да, но вызывается метод ЦЭ() из контекста класса БЭ, поэтому по идее должён возвращать переопределённую константу ЦЭ.

Родительский класс не имеет доступа к дочернему и если вызывают их методы то свойства берутся из родительского класса

(Отредактировано автором: 30 Декабря, 2010 - 20:00:28)



-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
Champion Супермодератор
Отправлено: 30 Декабря, 2010 - 20:24:13
Post Id



Активный участник


Покинул форум
Сообщений всего: 4350
Дата рег-ции: Авг. 2008  
Откуда: Москва


Помог: 57 раз(а)




Убедительная просьба, касающаяся всех: если вы недопонимаете вопрос, не отвечайте на него.
Отдельная просьба к, JustUserR, (в принципе, эту просьбу я уже много раз озвучивал, но он ее упорно игнорирует): хотя бы в больших текстах следует расставлять знаки препинания. Особенно, когда витееватые речевые обороты лежат друг на друге. Просто отсутствие запятых и, тем более точек, и несогласованность падежей слов сводет на нет глубокий (возможно) смысл всего написанного.
(Добавление)
А вопрос интересный. Виновато во всем позднее статическое связываение: http://habrahabr[dot]ru/blogs/php/23066/
Если с английским в хороших отношениях, то
http://www.php.net/manual/en/lan...tic-bindings.php
 
 Top
JustUserR
Отправлено: 30 Декабря, 2010 - 20:44:31
Post Id



Активный участник


Покинул форум
Сообщений всего: 8715
Дата рег-ции: Июнь 2009  


Помог: 17 раз(а)




like_you Описанное автором оригинальное функционирование PHP-приложения осущестлвяющего тестирование ООП-возможностей языка - в действительности является корректным
В качестве наиболее простого объяснения указанной ситуации может использоваться тот факт что вся ООП-реализация языка PHP в действительности представляет собой комбинацию именованных пространств имен и ссылок на объекты - с включением внутренних реализций синтаксических ООП-конструкций
Используемая в рассматриваемом приложении констуркция в действительности включает в себя действия по вызову переопределенного метода родительского класса вызываемого из его области - для включения собственной требуемой функциональности допустимо использование целевого метода в управляемом режиме из требуемого контекста


-----
Сделать можно все что угодно - нужно только старание, терпение и хороший поисковик Улыбка
Безлимитный web-хостинг от 15 рублей за 40 МБ дискового пространства - http://ihost[dot]oks71[dot]ru/
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Программирование на PHP »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB