Я задаю этот вопрос, потому что я полагаю, что они сделали это по очень веской причине, и что большинство людей не используют его должным образом, в любом случае, исходя из моего опыта работы в промышленности. Но если моя теория верна, то я не уверен, почему они включили модификатор частного доступа ...?
Я считаю, что при правильном использовании доступа по умолчанию он обеспечивает улучшенную тестируемость при сохранении инкапсуляции. И это также делает излишним модификатор частного доступа.
Модификатор доступа по умолчанию можно использовать для обеспечения того же эффекта, используя уникальный пакет для методов, которые необходимо скрыть от остального мира, и он делает это без ущерба для тестируемости, так как пакеты в тестовой папке с тем же возможность доступа ко всем методам по умолчанию, объявленным в исходной папке.
Я считаю, что именно поэтому Java использует доступ к пакетам как «по умолчанию». Но я не уверен, почему они также включили частный доступ, я уверен, что есть действительный вариант использования ...
Ответы:
Я думаю, у них было хорошее представление о том, что будет делать обычный программист. Под средним программистом я подразумеваю того, кто не очень хорош в программировании, но все равно получает работу, потому что не хватает хороших и они дорогие.
Если бы они сделали «публичный» доступ по умолчанию, большинство программистов никогда бы не стали использовать что-либо еще. Результатом будет много кода для спагетти повсюду. (Потому что, если вам технически разрешено вызывать что-либо откуда угодно, зачем вообще заключать инкапсулированную логику в метод?)
Если сделать «частный» доступ по умолчанию, это будет лишь немного лучше. Большинство начинающих программистов просто придумывают (и делятся в своих блогах) эмпирическое правило, что «вам нужно писать« публично »везде», а затем они будут жаловаться, почему Java настолько плоха, что вынуждает их писать «публично» везде. И они также будут производить много кода для спагетти.
Доступ к пакету - это то, что позволяет программистам использовать свои неаккуратные методы программирования при написании кода в одном пакете, но затем им приходится пересматривать его при создании большего количества пакетов. Это компромисс между хорошей деловой практикой и уродливой реальностью. Например: напишите немного кода для спагетти, если вы настаиваете, но, пожалуйста, оставьте безобразный беспорядок в пакете; по крайней мере, создать более приятные интерфейсы среди пакетов.
Возможно, есть и другие причины, но я бы не стал недооценивать эту.
источник
Доступ по умолчанию не делает модификатор частного доступа избыточным.
Позиция языковых дизайнеров отражена в официальном учебном пособии « Управление доступом к членам класса», и она достаточно ясна (для вашего удобства соответствующее утверждение в цитате выделено жирным шрифтом ):
Ваше обращение к тестируемости как к оправданию полного отказа от частного модификатора неверно, о чем свидетельствуют, например, ответы в разделе « Новое в TDD». Должен ли я избегать частных методов сейчас?
Позиция разработчиков языков в отношении цели и использования доступа на уровне пакетов объясняется в другом официальном учебном пособии « Создание и использование пакетов», и она не имеет ничего общего с идеей отбрасывания частных модификаторов (для вашего удобства соответствующее утверждение в цитате выделено жирным шрифтом ) :
<rant "Мне кажется, я услышал достаточно скуля. Думаю, пришло время сказать громко и ясно ...">
Частные методы полезны для модульного тестирования.
Примечание ниже предполагает, что вы знакомы с покрытием кода . Если нет, потратьте время на изучение, так как это весьма полезно для тех, кто заинтересован в модульном тестировании и вообще в тестировании.
Итак, у меня есть этот частный метод и модульные тесты, и анализ покрытия говорит мне, что есть пробел, мой частный метод не покрывается тестами. В настоящее время...
Что я получу от сохранения конфиденциальности
Так как метод является закрытым, единственный способ продолжить - изучить код, чтобы узнать, как он используется через не приватный API. Как правило, такое исследование показывает, что причиной разрыва является то, что в тестах отсутствует конкретный сценарий использования.
Для полноты, другими (менее частыми) причинами таких пробелов в покрытии могут быть ошибки в спецификации / дизайне. Я не буду углубляться в это здесь, чтобы все было просто; Достаточно сказать, что если вы ослабите ограничение доступа «просто для того, чтобы сделать метод тестируемым», вы упустите шанс узнать, что эти ошибки существуют вообще.
Хорошо, чтобы исправить разрыв, я добавляю модульное тестирование для пропущенного сценария, повторяю анализ покрытия и проверяю, что разрыв пропал. Что у меня сейчас? У меня есть новый модульный тест для конкретного использования не закрытого API.
Новый тест гарантирует, что ожидаемое поведение для этого использования не изменится без уведомления, так как если оно изменится, тест не пройдёт.
Внешний читатель может заглянуть в этот тест и узнать, как он должен использовать и вести себя (здесь внешний читатель включает в себя мое будущее Я, так как я склонен забывать код через месяц или два после того, как я закончу с ним).
Новый тест устойчив к рефакторингу (я делаю рефакторинг частных методов? Вы держите пари!) Что бы я ни делал
privateMethod
, я всегда хочу тестироватьnonPrivateMethod(true)
. Независимо от того, что я делаюprivateMethod
, не нужно будет изменять test, потому что метод не вызывается напрямую.Неплохо? Вы ставите.
Что я теряю от ослабления ограничения доступа
Теперь представьте, что вместо вышеупомянутого я просто ослабляю ограничение доступа. Я пропускаю изучение кода, который использует метод, и приступаю прямо к тесту, который вызывает мой
exPrivateMethod
. Большой? Не!Получу ли я тест для конкретного использования не частного API, упомянутого выше? Нет:
nonPrivateMethod(true)
раньше не было никакого теста , и сейчас такого теста нет.Получают ли сторонние читатели шанс лучше понять использование класса? Нет. - Эй, какова цель метода, проверенного здесь? - Забудь об этом, он предназначен исключительно для внутреннего использования. - Упс.
Это терпимо к рефакторингу? Ни в коем случае: что бы я ни изменил
exPrivateMethod
, скорее всего, это сломает тест. Переименуйте, объединитесь с другим методом, измените аргументы, и test просто прекратит компиляцию. Головная боль? Вы держите пари!Подводя итог , придерживаясь частного метода, я получаю полезное и надежное улучшение в модульных тестах. Напротив, ослабление ограничений доступа «для тестируемости» только дает мне неясный, трудный для понимания фрагмент тестового кода, который дополнительно подвергается постоянному риску быть нарушенным любым незначительным рефакторингом; Честно говоря, то, что я получаю, выглядит подозрительно, как технический долг .
</ Декламация>
источник
Наиболее вероятная причина: это связано с историей. Предок Java, Oak, имел только три уровня доступа: частный, защищенный, публичный.
За исключением того, что private в Oak был эквивалентом private пакета в Java. Вы можете прочитать раздел 4.10 Спецификации языка Oak (выделено мной):
Таким образом, на ваш взгляд, частного доступа, как известно на Java, изначально не было. Но когда у вас в пакете более нескольких классов, отсутствие приватного, как мы знаем, сейчас может привести к коллизии имен (например, java.until.concurrent имеет около 60 классов), поэтому, вероятно, они представил это.
Однако семантика доступа к пакету по умолчанию (первоначально называемая частной) не изменилась между Oak и Java.
источник
Бывают ситуации, когда хочется, чтобы два отдельных класса были более тесно связаны, чем публичное раскрытие всего. Это похоже на «друзья» в C ++, где другой класс, объявленный как «друг» другого, может получить доступ к своим закрытым членам.
Если вы загляните во внутренние классы, такие как BigInteger, вы найдете ряд пакетов защиты по умолчанию для полей и методов (все, что является синим треугольником в списке). Это позволяет другим классам в пакете java.math иметь более оптимальный доступ к их внутренностям для определенных операций (вы можете найти эти методы, вызываемые в BigDecimal - BigDecimal поддерживается BigInteger и снова сохраняет переопределение BigInteger . То, что это уровень пакета, не является ' Это проблема защиты, потому что java.math - это запечатанный пакет, и никакие другие классы не могут быть добавлены к нему.
С другой стороны, есть много вещей, которые действительно являются личными, как и должно быть. Большинство пакетов не запечатаны. Без private ваш коллега мог бы поместить другой класс в этот пакет и получить доступ к (больше не) приватному полю и нарушить инкапсуляцию.
Примечательно, что модульное тестирование не было тем, о чем думали в то время, когда создавались области защиты. JUnit (среда тестирования XUnit для Java) не была задумана до 1997 года (один рассказ об этом можно прочитать на http://www.martinfowler.com/bliki/Xunit.html ). Альфа- и бета-версии JDK были в 1995 году, а JDK 1.0 - в 1996 году, хотя уровни защиты реально не снижались до JDK 1.0.2 (до этого вы могли иметь
private protected
уровень защиты).Некоторые утверждают, что по умолчанию должен быть не уровень пакета, а частный. Другие утверждают, что не должно быть защиты по умолчанию, но все должно быть явно указано - некоторые последователи этого напишут такой код:
Обратите внимание на комментарий там.
Истинная причина, по которой защита на уровне пакетов используется по умолчанию, скорее всего, потеряна в заметках по проектированию Java (я копался и не могу найти никаких статей, почему многие люди объясняют разницу, но никто не говорит «это причина «).
Так что я сделаю предположение. И это все, что есть - предположение.
Прежде всего, люди все еще пытались понять языковой дизайн. С тех пор языки научились на ошибках и успехах Java. Это может быть указано как ошибка, так как не нужно определять что-то для всех полей.
public
, и,private
поскольку они оказывают наибольшее влияние на доступ.Таким образом, private не является дефолтом и все остальное стало на свои места. Область по умолчанию была оставлена по умолчанию. Это , возможно , было первой сферой , которая была создана и в интересах совместимости строгой обратных с старым кодом, осталась таким образом.
Как я уже сказал, это все предположение .
источник
Инкапсуляция - это способ сказать «вам не нужно об этом думать».
Помещая их в нетехнические термины.
источник
Я не думаю, что они сосредоточились на тестировании, просто потому что тогда тестирование не было распространенным явлением.
Я думаю, что они хотели добиться инкапсуляции на уровне пакета. Класс, как вы знаете, может иметь внутренние методы и поля и открывать некоторые из них только через открытые члены. Точно так же пакет может иметь внутренние классы, методы и поля и предоставлять только некоторые из них. Если вы думаете так, у пакета есть внутренняя реализация в наборе классов, методов и полей, а также открытый интерфейс в другом (возможно частично перекрывающемся) наборе классов, методов и полей.
Самые опытные программисты, которых я знаю, думают так. Они принимают инкапсуляцию и применяют ее к уровню абстракции выше, чем класс: пакет или компонент, если хотите. Мне кажется разумным, что разработчики Java уже настолько зрелы в своих проектах, учитывая, насколько хорошо Java все еще работает.
источник