За последние 24 часа нас посетили 17108 программистов и 1651 робот. Сейчас ищут 917 программистов ...

Не могу добраться до protected свойства

Тема в разделе "PHP для новичков", создана пользователем [code], 13 окт 2014.

  1. [code]

    [code] Новичок

    С нами с:
    14 июл 2014
    Сообщения:
    32
    Симпатии:
    0
    Добрый вечер! В общем, проблема состоит в том, что я, унаследовав класс, не могу обратиться к protected свойству родительского класса. Я уверен, что упустил какую-то мелочь, ночь уже.
    Код (Text):
    1.  
    2. class First{
    3.     protected $_test;
    4.     protected $_test2 = 'test2';
    5.     static $_instance;
    6.     public static function getInstance(){
    7.         if (!(self::$_instance instanceof self)){
    8.             self::$_instance = new self();
    9.         }
    10.         return self::$_instance;
    11.     }
    12.     private function __construct(){
    13.         $this->_test = 'test';
    14.     }  
    15.     public function test(){
    16.         return $this->_test;
    17.     }
    18. }
    19.  
    20. class Second extends First{
    21.     public function __construct(){}
    22.     public function test(){
    23.         return $this->_test;
    24.     }
    25.     public function test2(){
    26.         return $this->_test2;
    27.     }
    28. }
    29. $first = First::getInstance();
    30. $second = new Second;
    31. var_dump($second->test()); //null
    32. var_dump($second->test2()); //test2
    33. var_dump($first->test()); //test
    Почему при вызове $second->test() мне возвращается null, а не 'test'?
     
  2. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
  3. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    потому что у Second в классе свой конструктор. и там нет инициализации свойства $_test.

    Добавлено спустя 3 минуты 25 секунд:
    + приватные методы и свойства ненаследуются
     
  4. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    А, точно, это приваты не наследуются, а не протектед. Всё я перепутал.
     
  5. [code]

    [code] Новичок

    С нами с:
    14 июл 2014
    Сообщения:
    32
    Симпатии:
    0
    В первом классе protected метод, он должен наследоваться и свойство $_test инициализируется при создание экземпляра первого класса, разве нет?
     
  6. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    ты ж конструктор второго класса сделал пустым. в нём ничего и не происходит.
     
  7. [code]

    [code] Новичок

    С нами с:
    14 июл 2014
    Сообщения:
    32
    Симпатии:
    0
    Ну, все правильно. В первом классе обычный синглтон, у которого конструктор не наследуется, но до него можно добраться через getInstnace(), и он срабатывает. Потому что в конструкторе первого классе написано, чтобы он присваивал $_test значение 'test'. Потом если я к этому свойству обращаюсь через экземпляр первого класса, оно вызывается, а если через экземпляр второго класса, то выводит null.
     
  8. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    У тебя к $this->_test присваивается значение в конструкторе первого класса. А во втором классе ты конструктор похерил пустым. Соотв сюда ничего не вносится. Хочешь добраться до родительского свойства - используй обращение к свойствам родителя. Но это не $this будет.
     
  9. [code]

    [code] Новичок

    С нами с:
    14 июл 2014
    Сообщения:
    32
    Симпатии:
    0
    Тогда почему, когда я обращаюсь к $second->test2(), оно вызывает свойство родительского класса? В методе test2 описан вызов return $this->_test2
     
  10. Хыиуду

    Хыиуду Активный пользователь

    С нами с:
    3 июн 2014
    Сообщения:
    618
    Симпатии:
    5
    Потому что test2 у вас инициализируется прямо в момент объявления, а не в конструкторе.
     
  11. mkramer

    mkramer Суперстар
    Команда форума Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.600
    Симпатии:
    1.764
    Всё же элементарно:
    1. К private-членам (полям и методам) могут обратиться только методы того же класса (соответственно, конструктор First даже не доступен для вызова из Second)
    2. К protected-членам - методы класса и методы его наследников. Соответственно, поля First::$_test и First::_$test2 доступны для класса Second как обычно, через $this
    3. First::$_test2 у вас инициализирован при объявлении, поэтому он имеет значение для любого экземпляра First и Second, независимо от вызова конструктора
    4. First::$_test инициализируется в конструкторе First, который не вызывается для Second, да и не может быть вызван, поскольку он приватный, поэтому это поле для экземпляра Second остаётся пустым.
     
  12. [code]

    [code] Новичок

    С нами с:
    14 июл 2014
    Сообщения:
    32
    Симпатии:
    0
    Все, всем спасибо, во всем разобрался. Отдельное спасибо mkramer за подробный ответ.