Зачем нужен private?

~WR~

Новичок
В последнее время посещают мысли о вреде использования private функций и переменных.

Все знают, что private функции не видны в классах-потомках. И это вроде как призвано скрыть какие-то внутренние процессы в родителе, о которых знать не нужно. Для наследников этих функций не существует.

Ок, здорово. Представим себе, что эту фичу применили на практике.

Вася написал некий абстрактный класс, в котором объявил приватный метод getSize.
Петя написал свой класс, который унаследовал от абстрактного. Он вообще не смотрел в код Васи и сделал свой метод getSize, который делает что-то другое.

И так происходило еще несколько раз, пока уровней наследования не стало, скажем, пять.
А с третьего уровня какой-нибудь разработчик объявил свой getSize, но уже protected. И дальше они стали наследоваться уже с вызовами parent.

А потом прихожу я, и мне говорят: "Там какой-то getSize отвалился! Поправь ошибку, пожалуйста."
И нужно ломать мозг и разбираться в том, что методы с одинаковым названием на разных уровнях наследования могут быть вообще никак не связаны.

Разве это нормально?

-------------------------------

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

Ок, представим, что в примере выше появился Коля, который тоже унаследовал свой класс от абстрактного. Но ему вдруг понадобилось перегрузить оригинальный getSize. Он ставит protected, его код отлично работает. Но тут отваливается код Пети. Потому что он не рассчитывал на то, что у него вдруг вылезет оригинальный getSize, о котором он и не знал никогда.

По мне, так полная хрень.

-------------------------------

Разве не лучше всё и всегда объявлять как protected?

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

Это просто делает код более понятным и гибким в реальных задачах. Особенно если над ним работает несколько человек.

Такие вот мысли. What do u think?
 

itprog

Cruftsman
Петя написал свой класс, который унаследовал от абстрактного. Он вообще не смотрел в код Васи и сделал свой метод getSize,
Решать нужно источник проблемы, а не последствия. Если кто-то не посмотрел код, прежде чем писать свой (а вполне возможно что в getSize уже реализовано то, что хочет твой Петя), это не проблема private методов, а разработчика.

Protected не только способствует раскрытию внутренностей, но и автор абстрактного класса не может гарантировать работу своего класса (объявляя методы и данные как private, автор уверен, что они будут нести тот же смысл, который и задумывался. С protected же поведение этих методов может измениться в наследниках класса).
методы с одинаковым названием на разных уровнях наследования
А здесь есть rule of thumb: не использовать уже использованные названия на разных уровнях иерархии.
 

fixxxer

К.О.
Партнер клуба
Разве не лучше всё и всегда объявлять как protected?
Да. Либо protected либо если очень хочется final private.

Если кто-то не посмотрел код
А сфига ли я должен смотреть код? Интерфейс есть, дока есть.

Особенно этот аргумент действует в случае с Java, откуда PHP-шные private/protected/public родом и где исходный код библиотеки может быть вообще не доступен.
 
  • Like
Реакции: AmdY

itprog

Cruftsman
А сфига ли я должен смотреть код? Интерфейс есть, дока есть.
Если есть документация, то хорошо, можно воспользоваться и ей. Про какой интерфейс речь не совсем ясно, в нем не отражены protected методы.
 

fixxxer

К.О.
Партнер клуба
Про фактический интерфейс (сигнатура метода + phpdoc).
 

itprog

Cruftsman
А, это я имел в виду. Сигнатуру метода + phpdoc можно взять из кода, либо использовать тулзы и вытянуть их из кода.
 

fixxxer

К.О.
Партнер клуба
final private как раз и позволяет и это сделать и избежать упомянутой ТС проблемы.
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Проблема ТС высосана из пальца, имхо.

А потом прихожу я, и мне говорят: "Там какой-то getSize отвалился! Поправь ошибку, пожалуйста."
И ты таки не знаешь, какой отвалился? Сообщение об ошибке не содержит путь к файлу?

Зачем обьявлять как протектед те свойства, которые, скажем, внутри класса делают атомарные операции с данными и не должны быть открыты?

Мне кажется, что автор обьявлял private не то, что надо.
 

AmdY

Пью пиво
Команда форума
~WR~
ты случайно не со мной работаешь? у нас та же проблема и мы мучаемся. Поведение private нужно обеспечиваться юниттестами, а не жёстким запретом. Из-за этого получаются блокирующие баги, которые вроде и можно поправить но незя, потому что core private.
 

cDLEON

Онанист РНРСlub
Еще приходилось слышать такой вариант, что все методы лучше объявлять private. А если потом тебе нужно что-то перегрузить, то ты просто меняешь на protected и радуешься.
А я вот на сарае одном тоже видел надпись интересную.... Захожу - а там ДРОВА ЛЕЖАТ!!!!!
Приватный метод должен быть приватным ВСЕГДА! Если ставиться цель обратной совместимости. А то так можно скатиться до того, что зачем нам в объектах публичные функции! Ведь какой-нить Вася тоже может её переопределить и поменять весь предыдущий функционал...
 

cDLEON

Онанист РНРСlub
~WR~
ты случайно не со мной работаешь? у нас та же проблема и мы мучаемся. Поведение private нужно обеспечиваться юниттестами, а не жёстким запретом. Из-за этого получаются блокирующие баги, которые вроде и можно поправить но незя, потому что core private.
Если проблема в core, то что мешает править core ?
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Очередная тема о том чтобы защитить программиста от самого себя.
ООП - это иерархия и разделение как в коде, так и в коллективе.
Если автор меняет API и делает не-bc изменения, он обязан объявить о новой несовместимой версии.
Если у вас каждый кодер сам себе архитектор и меняет базовые классы не обсуждая с другими - это не проблемы ООП, а быдлокодинг.

Я сторонник private, они позволяют выработать стабильный интерфейс фреймворка и дорабатывать реализацию, сохраняя совместимость API.
Т.е. без private станут невозможны minor-релизы фреймворков и библиотек.
 

~WR~

Новичок
Да все ок. Final действительно решает проблему повторного использования имени функции.
Причем на php.net есть несколько комментариев, в которых люди пишут, что в "правильном" ООП это вроде бы не должно работать, но в PHP работает. :)

ты случайно не со мной работаешь?
Не, я из мск)
Просто попросили помочь с одним проектом по старой памяти.
А там, за полгода моего отсутствия, появилась описанная выше жуть.

И подумалось, что если бы оно изначально было сделано по-другому, то не прошлось бы ломать голову сейчас.
Извините, если маленький холивар развел. ^__^
 

~WR~

Новичок
Если проблема в core, то что мешает править core ?
Кстати, правка ядра в большом проекте может быть оказаться той еще проблемой.

Даже исправления явных багов могут отвергаться главными архитекторами с формулировкой: "Идея правильная, но вдруг кто-то уже использует это как фичу? Пока все работает, я не хочу рисковать." И, черт возьми, я их понимаю. Если что случится - отвечать будут они в первую очередь.
 

itprog

Cruftsman
Причем на php.net есть несколько комментариев, в которых люди пишут, что в "правильном" ООП это вроде бы не должно работать, но в PHP работает.
А какая связь между модификаторами доступа (в мануале пхп какого-то хрена это называется "областью видимости") и модификаторами управления переопределением методов?
 

fixxxer

К.О.
Партнер клуба
Кстати, правка ядра в большом проекте может быть оказаться той еще проблемой.

Даже исправления явных багов могут отвергаться главными архитекторами с формулировкой: "Идея правильная, но вдруг кто-то уже использует это как фичу? Пока все работает, я не хочу рисковать." И, черт возьми, я их понимаю. Если что случится - отвечать будут они в первую очередь.
1) логируем все такие обращения к api с бэктрейсом
2) svn blame
3) "мы вот тут это меняем, пофикси пожалуйста".
 

AmdY

Пью пиво
Команда форума
А какая связь между модификаторами доступа (в мануале пхп какого-то хрена это называется "областью видимости")
Как же хорош мануал по php, ведь действительно, как ни печально, но в php нет рельных модификаторов доступа ибо их легко можно обходить пробрасыванием объекта.
PHP:
class Foo {
    protected function testFoo() {
        echo __METHOD__ . "<br/>";
    }
}
class Bar extends Foo {
    public function testFooFromBar($foo) {
        $foo->testFoo();
    }
}
$foo = new Foo();
$bar = new Bar();
$bar->testFooFromBar($foo); // вызван протектид метод Foo::testFoo
$foo->testFoo(); //Fatal error: Call to protected method Foo::testFoo() from context ''
 

fixxxer

К.О.
Партнер клуба
Это by design. И очень полезный by design. В Java поведение такое же. А в С++ как раз не так - и приходится городить костыли с friend-ами.
 

itprog

Cruftsman
Как же хорош мануал по php, ведь действительно, как ни печально, но в php нет рельных модификаторов доступа ибо их легко можно обходить пробрасыванием объекта.
у модификаторов доступа есть идея контекста. testFoo вызывает объект класса Bar (не важно, каким образом) , который отнаследован от Foo и соответственно имеет доступ к протектид методу. И в C# так же.
 
Сверху