Можете привести пример, когда использовать private, а когда protected?
Чтобы поменять что-то в классе, не нужно изменять его код - нужно применить паттерн декоратор.
Есть принцип проектирования: "предпочитайте композицию наследованию, а так же принцип: "проектируйте на уровне абстракций".
В целом, если можно создать объект класса - не стоит от него наследоваться, лучше делегируйте в новом классе часть функционала на такой объект и добавьте новый функционал, как-то так.
Понятное дело, private нужен для случаев, когда наружу ничего не должно выходить (разве что через геттер).
Protected же полезен при принципе проектирования на уровне абстракций, когда можно выделить общее (и сделать protected) и отделить изменяющееся (еще один принцип, кстати).
Свойства всегда приватные, исключением может быть например массив конфига с параметрами по умолчанию, чтоб переопределять в наследниках свойство, методы которые описывают интерфейс всегда публичные, защищенные если надо дергать их из наследников, приватные это методы помощники, которые не относятся к интерфейсу и просто что то делают под капотом