Доступ к приватным свойствам родительского класса, парадигма ООП или баг?

dimagolov

Новичок
Наследование - это взяли и скопировали один объект в другой. Какая тут инкапсуляция?
А зачем тогда понадобился уровень доступа private? С такой логикой и protected достаточно...
 

whirlwind

TDD infected, paranoid
А при чем здесь private? private нужен что бы обеспечить работу по принципу - закрыт от изменений, доступен для расширения. Инкапсуляция по сути это отношение к объекту снаружи. А при наследовании получается не два объекта, а гибрид двух классов.
 

Вурдалак

Продвинутый новичок
Автор оригинала: whirlwind
private нужен что бы обеспечить работу по принципу - закрыт от изменений, доступен для расширения
— «доступен для расширения»? В каком смысле?
 

phpamid

Новичок
Очень круто, топик дня, но тема уже отклонилась от курса. :)
----------------------------------------------------------------------------------

Смотрим мой первый пост и по возможности отвечаем на заданный вопрос, учитывая следущее:

... т.к. в наследнике есть переменная
private $my_private_member = 'Son private member'; . Соответственно наследуемый метод public function show_private_member() должен был вывести значение свойства наследника.
 

Вурдалак

Продвинутый новичок
phpamid, давай по-другому: у тебя, положим, нет в дочернем классе этого атрибута. Как должен вести себя метод show_private_member()?
 

weregod

unserializer
phpamid
private свойства имеют область видимости для методов именно того класса, в котором свойства описаны.
 

phpamid

Новичок
Автор оригинала: weregod
phpamid
private свойства имеют область видимости для методов именно того класса, в котором свойства описаны.
Собственно я об этом и "твердю":

1) Son унаследовал (как было раньше сказано - "взял в аренду" и т.д.) метод родителя.
2) private свойство описано в Son


-----------------------------------------------------------------------------------------------------------------
Интересная получается штука (тут же кроется и ответ на последний вопрос Вурдалака):

PHP:
	class Father 
	{
		//private $my_private_member = 'Father private member';
		public function show_private_member()
		{
			echo $this->my_private_member;
		}
	}
	class Son extends Father { 
		private $my_private_member = 'Son private member';
	}

	$son_instance = new Son;
	$son_instance->show_private_member();
- К приватным свойствам класса наследника (Son) имееют доступ только те методы, которые реализованы/переопределены в этом классе (Son), у public/protected методов наследников в классе Son - нет доступа.

Исходя из этого, если в классе Son есть "свойства приватники", то работать с ними можно только через методы, которые реализованы/переопределены, Son класса.

Еще пример "в догонку":

PHP:
class Father 
{
	private $my_private_member = 'Father private member';
	public function show_private_member()
	{
		echo $this->my_private_member;
	}
}
class Son extends Father { 
	private $my_private_member = 'Son private member';
}
class Baby extends Son { 
	private $my_private_member = 'Baby private member';
}
class BabySon extends Baby { 
	private $my_private_member = 'BabySon private member';
}

$babyson_instance = new BabySon;
$babyson_instance->show_private_member();
Как бы ожидали: "BabySon private member"
Получили: "Father private member"
----------------------------------------------------------------------------------------------------------------------------------------------------------------------

Я думаю тема рассмотрена достаточно тщательно, чтобы поставить точку, но еще бы пару моментов:


1) Интересен результат в Java и других, по возможности, языках.
2) Найти док "мат.часть" ООП, где это написано-описано или все это "логичный вывод".

- было бы полным и вкусным "компотом" по этой теме.


p.s Заранее Всем спасибо за интересную беседу, ответы и внимание.
 

Adelf

Administrator
Команда форума
phpamid
Все-таки когда приводишь код - пости хотя его результат.

Fatal error: Cannot access private property Son::$my_private_member in T:\home\localhost\www\4.php on line 7

Это на твой первый код :) Вот это уже можно считать багом. Метод отца хочет получить доступ к свойству сына. Хотя... это же PHP. Статически-типизированный язык выдал бы ошибку компиляциию.. а PHP ничего другого не остается кроме как выкручиваться.

Java:
PHP:
class Father 
    {
        private String my_private_member = "Father private member";
        public void show_private_member()
        {
             System.out.println(this.my_private_member);
        }
    }

class Son extends Father 
{ 
	private String my_private_member = "Son private member";
}

public class test {

	/**
	 * @param args
	 */
	public static void main(String[] args){
		// TODO Auto-generated method stub

		Son son_instance = new Son();
	    son_instance.show_private_member();
	}

}
Вывод: Father private member

Я то не сомневался... :)

-~{}~ 31.07.10 14:12:

phpamid
Я помоему уже все как мог обьяснил. Что именно тебе непонятно?
 

MiksIr

miksir@home:~$
Автор оригинала: phpamid
Как бы ожидали: "BabySon private member"
Получили: "Father private member"
ВЫ ожидали. А мы - нет. Еще раз - если следовать вашей логике, то любое наследование от родительского класса делает невозможным использование приватных свойств в принципе. Типа, работал класс работал - отнаследовали - все перестало работать. Это, по вашему, логично? Ну тогда странная логика у вас.
 

phpamid

Новичок
Автор оригинала: Adelf
phpamid
Все-таки когда приводишь код - пости хотя его результат.

Fatal error: Cannot access private property Son::$my_private_member in T:\home\localhost\www\4.php on line 7

Это на твой первый код :) Вот это уже можно считать багом. Метод отца хочет получить доступ к свойству сына. Хотя... это же PHP. Статически-типизированный язык выдал бы ошибку компиляциию.. а PHP ничего другого не остается кроме как выкручиваться.

Java:
PHP:
class Father 
    {
        private String my_private_member = "Father private member";
        public void show_private_member()
        {
             System.out.println(this.my_private_member);
        }
    }

class Son extends Father 
{ 
	private String my_private_member = "Son private member";
}

public class test {

	/**
	 * @param args
	 */
	public static void main(String[] args){
		// TODO Auto-generated method stub

		Son son_instance = new Son();
	    son_instance.show_private_member();
	}

}
Вывод: Father private member

Я то не сомневался... :)

-~{}~ 31.07.10 14:12:

phpamid
Я помоему уже все как мог обьяснил. Что именно тебе непонятно?
1) Спасибо, что запостил результат кода ... )))
- ты акцентировал внимание на баге, значит ты не понял, что я хотел сказать.
перечитай еще раз мой пост и обрати внимание на выделенные слова.
2) Спасибо за пример с Java. (искренне)
3) Одного не понимаю, сколько раз пишу, а ты все о своем:

Еще раз, для тебя лично: :)

Я думаю тема рассмотрена достаточно тщательно, чтобы поставить точку, но еще бы пару моментов:

1) Интересен результат в Java и других, по возможности, языках. (за это я тебя поблагодарил)
2) Найти док "мат.часть" ООП, где это написано-описано или все это "логичный вывод".

Не суди строго, но вроде я четко изложил второй пункт. :)


-~{}~ 31.07.10 13:58:

Автор оригинала: MiksIr
ВЫ ожидали. А мы - нет. Еще раз - если следовать вашей логике, то любое наследование от родительского класса делает невозможным использование приватных свойств в принципе. Типа, работал класс работал - отнаследовали - все перестало работать. Это, по вашему, логично? Ну тогда странная логика у вас.
Внимательно перечитайте пост.

Или если Вам удобно - аргумент в студию по поводу Ваших слов: "любое наследование от родительского класса делает невозможным использование приватных свойств в принципе".
 

Adelf

Administrator
Команда форума
phpamid
Ну я могу тебе уверенно сказать что на С++ тоже также(я знаю как обьекты и их методы там выстраиваются в памяти). И на C#. Я думаю вполне достаточно.. более правильных обьектно-ориентированных языков(не считая Smalltalk) больше нет.
 

MiksIr

miksir@home:~$
А очень просто. private свойства видны только в пределах класса, в дочерних не видны - это аксиома.

Если вы утверждаете, что методы родительского класса унаследованные в дочернем должны работать в контексте дочернего класса, и обращаться к приватным свойствам дочернего класса, то нет никакой возможности добраться тогда до приватных свойств родительского класса.

Еще раз другими словами, если вы утверждаете, что после создания объекта $o = new Son() все методы работают в контексте Son, ибо унаследованы туда от Father и должны работать с приватными свойствами Son, то как добраться до приватных свойств Father? Да никак вообще - только разве что из приватных методов... вызвать которые, правда, не получится по тем же самым причинам.

Ситуация выглядит маразматично настолько, что не стоит и обсуждения.

Вы пытаетесь играть на том, что типа у вас своиства с одинаковыми именами. Но это в случае private ничего не значет совершенно. private на то и private, что бы Son ничего не знал о них впринципе. По-этому от того, что свойства с одинаковыми именами или разными - логика описанная выше меняться не может - ибо тогда это уже будет не private.

-~{}~ 31.07.10 15:34:

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

A1x

Новичок
ок, пусть будет декоратор - как пример когда классу-потомку не надо иметь прямого доступа к какому-то свойству родительского класса

проверил на Java - c private ведет себя так же как пхп
НО когда меняю private на protected Java продолжает вести себя так-же (как ни странно), тогда как пхп ведет по-другому (как и ожидалось)

Теперь непонятно поведение Java с protected, может кто-то объяснить? (сори за офтоп :)
 

MiksIr

miksir@home:~$
Автор оригинала: A1x
НО когда меняю private на protected Java продолжает вести себя так-же (как ни странно), тогда как пхп ведет по-другому (как и ожидалось)
И в дочернем и в родительском поменял?
 

A1x

Новичок
да
Код:
public class Father {

    protected String hello = "Father says hello";

    public void hello() {
        System.out.println(this.hello);
    }
}

public class Son extends Father {

    protected String hello = "Son says hello";

}

Father f = new Father();
f.hello();
Son s = new Son();
s.hello();
результат
Father says hello
Father says hello
 

dimagolov

Новичок
вообще-то желаемое phpamid-м поведение достигается абстрактными методами, которые ДОЛЖНЫ переопределяться в наследниках.

и вообще, не путайте классы которые разработаны как базовые для наследования и те, от которых МОЖНО наследовать. логика написания таких классов серьезно разнится.
 

Вурдалак

Продвинутый новичок
dimagolov, почему «должны»? Тогда бы и интерфейса хватило. Просто есть некий общий функционал, который как раз-таки переопределять необязательно.
 
Сверху