Сразу скажу, что основной язык у меня C#, поэтому мыслю в его парадигме.
Там модификаторы доступа работают аналогично Java, за исключением protected. В C# он означает "доступен только в классе и его потомках", а неймспейс (некий аналог пакета в Java) роли не играет. Т.е. получается этакий "private для меня и потомков".
Т.е. сценарии такие:
1. Нужен доступ вообще отовсюду - пиши public.
2. Нужен доступ только внутри класса - пиши private.
3. Нужен доступ только внутри класса и потомках - пиши protected.
4. Нужен доступ отовсюду, но только в пределах неймспейса ("пакета") - пиши internal.
В Java же protected - это доступ всем в том же пакете, а в других пакетах - только потомкам.
Я не могу понять, какой смысл давать полный доступ всем в таком же пакете? Получается у нас выпадает сценарий 3.
Например, я хочу создать класс Сотрудник (с потенциальными подклассами АутсорсСотрудник, СвойСотрудник), у него поля Имя, Фамилия. Хочу, чтобы они наследовались, значит я должен объявить их как protected. Но тогда они станут видны извне самих классов и условный класс X, получив ссылку на сотрудника, сможет ему изменить поле Имя или Фамилия напрямую, в обход методов-сеттеров.
В общем сейчас для меня такой protected выглядит абсурдным. Объясните, в чем дело, почему он именно такой?
Я не могу понять, какой смысл давать полный доступ всем в таком же пакете?
ну раз не видишь, не используй, в мире полно вещей которые тебе никогда и не понадобятся
в самом деле за несколько лет ни разу не использовал protected, но пару раз встречал
Да, но прямое присвоение поля в обход сеттера - это нарушение инкапсуляции и если в сеттере логика проверки, то прямое присвоение может что-то неправильное поместить.
В этом мало смысла. Это классы сущностей, которые должны быть публичными, т.к. в условном соседнем пакете будут классы, которые с ними работают.
Похоже в джаве просто несколько другой подход к наследованию, более "формальный" что ли. Т.е. между подклассом и суперклассом отношения тоже формально-строгие в плане доступа к поялм. Все поля родителя объявляются как private и хотя наследуются потомками, но доступны только через публичные сеттеры с явным указанием super.setSome(...). В С# такое же поведение private, т.е. они наследуются, но напрямую недоступны, а вот если хочешь с полями родителя работать как со своими, объявляй их protected и не парься.
Дмитрий, в этом есть смысл если у тебя есть базовый пакет OAuth авторизации с непубличным классом OAuthAdapter и публичным OAuthManager + пакеты-наследники реализующие OAuthAdapter. Доступ к адаптерам декорируется/проксируется менеджером который по сути выступает публичным api/точкой для взаимодействия с пакетами OAuth