Наследование и модификаторы доступа

barthon

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

Пример:

PHP:
class a {
   
     private $myvar='a';
   
     function my() {  
         echo $this->myvar;
         echo '<br>';    
         var_dump($this);
     }

}


class b extends a {
   
     public $myvar='b';      
   
}


$b=new b;
$b->my();
Результат:
a
object(b)#1 (2) { ["myvar"]=> string(1) "b" ["myvar":"a":private]=> string(1) "a" }

Почему отображается "а"? Каков четкий алгортм определения какое значение свойства будет доступно?

P.S. мой вопрос относится ко всем возможным комбинациям модификаторов:
private/private - 'a'
private/protected - 'a'
private/public - 'a'
protected/protected - 'b'
protected/public - 'b'
public/public - 'b'
 
Последнее редактирование:

Adelf

Administrator
Команда форума
не играй в эти игры. В нормальных языках тебе просто не дадут создать это поле в классе b.
 

Lionishy

Новичок
@barthon
Код функции my в классе a связан с контекстом класса a, потому и имя myvar связывается с данными в контексте a.
Переменная myvar в классе b -- это имя уже в новом контексте. Вызов же функции my для объекта класса b передаётся "внутреннему объекту" класса a, который и обрабатывает сообщение, вызывая функцию my из своего контекста, где имя myvar связано с данными 'a'.
Если функцию my переопределить в классе b с точно таким же кодом, то будет уже вызвана функция my в контексте b и имя myvar связано в контексте b c данными 'b'.
 

barthon

Новичок
>Код функции my в классе a связан с контекстом класса a, потому и имя myvar связывается с данными в контексте a.
Думаю, это неверно, так как в объяснении нет привязки к комбинации модификаторов доступа в базовом и производном классе.
Если протестировать разные комбинации модификаторов, можно получить разные результаты, в том числе с доступом к b::$b:
protected/protected -> 'b'
protected/public -> 'b'
и т.д.

>"Внутренний объект" ....
Тоже странная формулировка ...

Кроме того бывает 2 контекста: контекст объекта и контекст класса. Здесь есть только контекст объекта ...
"Внутреннего объекта" тоже нет, есть вызываемый объект ($b), на который и ссылается псевдо-переменная $this.
 

AnrDaemon

Продвинутый новичок
Потому что protected свойства наследуются, а private - копируются.
 

WMix

герр M:)ller
Партнер клуба
не играй в эти игры. В нормальных языках тебе просто не дадут создать это поле в классе b.
мне кажется это нормальное поведение при наследовании (вроде в java и c++ это возможно). другой вопрос какую переменную должен вернуть a::getA() когда у нас инстанц:b
 

barthon

Новичок
>Потому что protected свойства наследуются, а private - копируются.
1. А чем копирование отличается от наследования?
2. И как это поясняет проблему с комбинацией private/public?
 

Adelf

Administrator
Команда форума
мне кажется это нормальное поведение при наследовании (вроде в java и c++ это возможно). другой вопрос какую переменную должен вернуть a::getA() когда у нас инстанц:b
Вот из-за этих вопросов я и советую не играть в эти игры. Когда ты программируешь ты должен просто решить задачу. Любое неявное поведение отвлекает тебя от задачи. Ты должен думать как оно себя поведет и т.д. Не должно в нормальном коде возникать ситуации, когда тебе надо думать что там приватного у родителя или у потомка.

private/private - 'a'
private/protected - 'a'
private/public - 'a'
protected/protected - 'b'
protected/public - 'b'
public/public - 'b'
Помоему понятно, что private работает так как и должен.
 

AnrDaemon

Продвинутый новичок

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Потому что protected свойства наследуются, а private - копируются.
по-моему, это определение - полная хрень
в php расширение области видимости поля разрешено для обратной совместимости - просто потому что все привыкли, что можно
хорошо хоть решились на принуждение к соблюдению Лисковой, когда в 5.2 или 5.3 при наследовании запретили менять сигнатуру методов

копирование zval происходит всегда одинаково - и при наследовании, и при реализации интерфейса
 
Последнее редактирование:

AnrDaemon

Продвинутый новичок
Полная или частичная, зато хорошо описывает поведение. :) И заметь, ты сказал "по-момему", значит, у тебя есть сомнения.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
да, есть сомнение в формулировке "полная хрень"
однако, если написать, что я считаю тезис о копировании свойств некорректным, новичкам, назовем их так, будет непонятно

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

Adelf

Administrator
Команда форума
А вам не пофиг как оно реализовано?
Вам слово private хоть о чем нибудь говорит?
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
вот только давай не начинать про консистентность и логичность PHP )))

как в грузинской школе: льожька пишется без мягкого знака, а шмэл - с мягким знаком, и понять это нэвазможно
 

Adelf

Administrator
Команда форума
Ну здесь то он он реализует все верно. Зачем придумывать всякие обьяснения, которые новички не смогут понять. Можно просто сказать, что private доступно только в этом классе и нигде более(про рефлексию будем молчать, правда я хз как в PHP. В C# можно добраться.).
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
чтобы у них был шанс перестать быть новичками, а не думать, что объекты - это феи, которые какают радугой

вот мне этого никто не объяснял пока я не прочел описание работы zval
 

Adelf

Administrator
Команда форума
@grigori, ну тогда по твоей классификации я - новичок. Я знать не хочу как в PHP реализована приватность. Мне важно лишь, что оно работает как надо.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
я верю, что совершеннолетние инженеры способны решить самостоятельно что им нужно, и беречь их от реальности не надо
не хочешь знать - не разбирайся, хочешь - вот корректный базовый алгоритм, без сказок про бассейны :)

мы не журналисты
 
Последнее редактирование:

Adelf

Administrator
Команда форума
Мне больше нравится другой алгоритм. Это работает так. Если хочешь знать почему - спроси - расскажем, укажем где прочитать. Не хочешь - твоё право.
Это не ... блин. Ты почти каждый пост редактируешь после публикации :) отучайся.
Вощем это не оберегание от реальности, а оберегание от не всегда нужной детализации.
Когда учат машину водить ведь не описывают как на самом деле работает педаль газа и что она конкретно делает. Вполне достаточно инфы об эффекте этой педали.
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
PHP:
class A{
private $x=1;
public function foo(A $A){ echo $A->x;}
}
Class Aa extends A{
private $x = 2;
public function bar(A $A){ echo $A->x;}
}
$a = new A;
$aa1 = new Aa;
$aa2 = new Aa;
$a->foo($aa1);
$aa2->foo($aa1);
$aa2->bar($aa1);
 
Сверху