Страницы

Поиск по вопросам

воскресенье, 24 ноября 2019 г.

В чем преимущества использования закрытых (private) методов в классе?


В чем преимущества использования закрытых (private) методов в классе, кроме скрытых вычислений?
    


Ответы

Ответ 1



При написании достаточно большого куска кода (неважно, класса, функции или чего-нибуд ещё) важным приёмом является декомпозиция. Вы делите функциональность на логические части, и в главной функции складываете из них, как из кирпичиков, общую логику. При этом сами кирпичики могут быть не приспособлены для доступа снаружи. Например открытый метод может проверять входные параметры, а вспомогательным методам-кирпичика это уже не нужно, т. к. они вызываются лишь изнутри. Если бы эти методы были открытыми, в них нужно было бы реализовывать проверку параметров, и при их имплементации нельзя было бы рассчитывать на то, что они будут вызваны в контролируемый вами момент. Кроме того, внутренние методы имеют право портить состояние класса, если вы знаете что вызывающий их код потом эту проблему исправит. Если сделать эти методы открытыми, пользователи этого класса смогут испортить внутреннее состояние класса без исправления. Затем, внутренние методы могут не иметь ничего общего с тем, что должен предоставлят класс, с его внешним интерфейсом. Например, если класс представляет машину, то открытый метод в нём, переводящий дюймы в сантиметры, смотрелся бы нелепо. А вот внутри такой перевод вполне может понадобиться. Ну и в конце-концов, публичный метод — это обещание для пользователей. Каждое изменени (удаление, изменение сигнатуры, а иногда и добавление) открытого метода — breaking chang для клиентов, они должны пересмотреть код, который использует ваш класс. Таким образом вы не должны просто так, без особой на то необходимости менять открытые методы класса. А вот изменения в закрытых методах обычно происходят при рефакторинге в массовом порядке: методы упрощаются, объединяются, раскладываются на несколько, переносятся вверх-вниз по иерархии, меняется их семантика, и всё это никак не отражается на пользователях вашего класса.

Ответ 2



Чтобы добавить что-то, private метод может ВСЕГДА безопасно меняться, потому чт вы точно знаете, что вызывается только из собственного класса, никакие внешние классы не могут вызвать private метод (они даже не видят его). Таким образом, наличие private метода всегда хорошо, поскольку вы знаете, что не никаких проблем по его изменению, даже вы можете безопасно добавить дополнительные параметры в метод. Что касается о public методах, любой может вызвать этот метод, поэтому, если вы добавляете/удаляете параметр, вам также нужно будет изменить ВСЕ вызовы этого метода. Вот некоторые преимущества создания переменных или методов private в Java: частные методы хорошо инкапсулированы в классе, и разработчик знает, что они не используются где-либо еще в коде, что дает им уверенность в изменении, изменении или улучшении частного метода без какого-либо побочного эффекта. Если посмотреть на закрытый метод, вы наверняка знаете, что никто его не использует, что очень помогает при отладке java-программы. IDE, например Netbeans, IDEA и Eclipse, используют эту информацию и автоматически проверяют, используются ли частные методы внутри класса или нет, и могут отображать соответствующее предупреждение для улучшения качества кода или удаления неиспользуемых операторов, переменных или методов. Частные методы используют статическую привязку в Java, и они связываются во время компиляции, которое быстро сравнивается с динамическим связыванием, которое происходит во время выполнения, а также дает JVM шанс либо встроить метод, либо оптимизировать его. Присвоение переменных приватным в java и предоставление им getter и setter делает ваш класс совместимым с именованием бинов Java и другими структурами на основе отражения, такими как displaytag. Неплохая (на мой взгляд) статья на эту тему

Ответ 3



Сделав метод закрытым, совсем не обязательно его сохранять при переходе к другой реализации. Такой метод труднее реализовать, а возможно, он окажется вообще ненужным, если изменится представление данных, что, в общем, несущественно. Важнее другое: до тех пор, пока метод является закрытым (private), разработчики класса могут быть уверены в том, что он никогда не будет использован в операциях, выполняемых за пределами класса, а следовательно, они могут просто удалить его. Если же метод является открытым (public), его нельзя просто так опустить, поскольку от него может зависеть другой код. Источник - Хорстманн К., Корнелл Г.-Java 2. Основы. Том 1-Вильямс (2014)(стр 158)

Ответ 4



В общем и целом -- все нереально просто. Значительно проще, чем многие здесь написали :) Появлению приват-модификатора обязан один из главных принципов ООП -- инкапсуляция Основная идея инкапсуляции -- сделать приватными максимум методов/проперти, которые возможно сдалать приватными. Как следствие мы имеем: Более простую структуру кода: разделение внутренне важной реализации(приваты) и органов управления(паблики). Более удобные подсказки (когда ставишь точку и тебе предлогают выбрать метод/параметр) -- IDE не показывает ничего "лишнего"(только паблики) при использовании класса. Безопасный код (защита от дурака) Невозможно по-дурости вызвать метод с другого класса который с него вызывать НЕ нужно (вот есть у тебя микроволновка -- у тебя есть доступ к Запустить() и ИзменитьВремя() но нету доступа к ИзменитьЧастотуВолн() [это уже внутрення реализация к которой не нужно давать доступ "смертным" что бы и не запутать и не навредить твоему инстансу класса бездумным изменением параметров руками смертных]) Невозможно извне изменить проперти, которую не нужно изменять извне. (ЧастотаВолн) [то же самое] Возможность под корню изменять всю нутрянку класса(все приваты) не ламая при это "внешний код", который работает исключительно с пабликами даного класса останется рабочи как и прежде. Ты можешь под корню изменить ВСЮ внутреннюю реализацию микроволновки - заменить все запчасти, вставить другие платы, но все публичные метды и параметры останутся на месте. Визуально микроволновка, даже, не изменится -- пользователь, даже, не догадается, что что-либо изменилось, окроме того что она стала субьективно или обьективно лучше работать. Как заметил Barmaley -- это еще и инструмент для планирования следующих релизов Мы можем закрывать доступ к некоторым фичам/методам/параметрам, которые пока что сырые, что бы их не использовали пользователи класса до какого-то конкретного релиза. ИТОГО: В следствии использовании принципа инкапсуляции у програмиста уменьшаетс возможность допустить ошибку по-дурости и повышается производительность на средне-малых, средних и больших проэктах т.к. код становится проще и безопаснее при изменении самого класса. (На совсем малых проэктах в пару малых классов производительность программиста может упасть за счет "лишних действий", но по-факту, оно того все равно стоит)

Ответ 5



off-topic Если есть private метод - это уже приглашение к хакингу, а именно вызов приватног метода через Java Reflection API - легко гуглится, не буду даже приводить примеры как это делается. В этом контексте забавно читать: private методы и переменные видны только внутри класс. Их не видят никакие постороннме классы. Даже их дети. Это делают для предотвращения нежелательного изменения данных извне. Теперь к сути вопроса ТС Приватные методы делают иногда для того, чтобы потом когда нибудь их сделать публичными Я лично наблюдал это на примере SMS/MMS API в Android'е, когда в ранних версиях Android методы работы с SMS были в основном скрыты/private, а потом где-то в районе KitKat их начали открывать (декларировать public) и громогласно объявили о новых API :) Так что кроме инкапсуляции я вижу плюс использования приватных методов еще как средство планирования будущих релизов.

Ответ 6



Как официальный ответ: private-модификатор - это часть инкапсуляции данных. Инкапсуляция предохраняет данные объекта от нежелательного доступа, позволяя объекту самому управлять доступом к своим данным. Свой вариант ответа: есть такое понятие, как API (application programming interface) С точки зрения java-класса, его public-методы являются его API, т.к. через эти метод с этим java-классом можно взаимодействовать в своем коде. В свою очередь, private-метод всегда скрыты извне. Соответственно модификация private-методов не затронет сигнатуры public-методов. То есть все внешние взаимодействия с этим java-классом, после модификации его private-методов, скорее всего, не потребует доработок. И это преимущество private-методов!

Ответ 7



Есть такое понятие- инкапсуляция. Т.е пользователям твоего класса не следует знать о внутреннем устройстве твоего класса. Пользователь должен взаимодействовать с полями, через специальные методы, которые не позволяют сделать , например, некорректного присвоения.

Ответ 8



Обобщу ответы private-модификатор - это часть инкапсуляции данных. Инкапсуляция предохраняет данные объекта от нежелательного доступа, позволяя объекту самому управлять доступом к своим данным. Для закрытого члена класса нельзя задать значение непосредственно в коде за пределам класса. Но в то же время можно полностью управлять тем, как и когда данные используютс в объекте. Следовательно, правильно реализованный класс образует некий “черный ящик”, которым можно пользоваться, но внутренний механизм «его действия закрыт для вмешательства извне. Java Язык программирования java имеет множество возможностей для сокрытия информации Одна из них - механизм управления доступом (access control), задающий степень доступност (accessibility) для интерфейсов, классов и членов классов. Доступность любой сущности определяется тем, в каком месте она была декларирована и какие модификаторы доступа, если таковые есть, присутствуют в ее декларации (private, protected или public). Как следствие мы имеем: 1 Более простую структуру кода (ты точно видишь где внутренне важная реализация а где важная для внешних обьектов) 1.1 При написании достаточно большого куска кода (неважно, класса, функции или чего-нибуд ещё) важным приёмом является декомпозиция. Вы делите функциональность на логические части, и в главной функции складываете из них, как из кирпичиков, общую логику. При этом сами кирпичики могут быть не приспособлены для доступа снаружи. Например открытый метод может проверять входные параметры, а вспомогательным методам-кирпичика это уже не нужно, т. к. они вызываются лишь изнутри. Если бы эти методы были открытыми, в них нужно было бы реализовывать проверку параметров, и при их имплементации нельзя было бы рассчитывать на то, что они будут вызваны в контролируемый вами момент. 2 Кроме того, внутренние методы имеют право портить состояние класса, если вы знаете что вызывающий их код потом эту проблему исправит. Если сделать этим методы открытыми, пользователи этого класса смогут испортить внутреннее состояние класса без исправления. 3 Безопасный код 3.1 Невозможно по-ошибке вызвать метод с другого класса который с него вызывать не нужно. 3.2 Невозможно извне изменить проперти, которую не нужно изменять извне. 4 Возможность изменять реализацию внутренней структуры класса(все что относится приватам) не ламая при этом "внешний код", который привязан исключительно к пабликам. 4.1. В совместных проектах у программистов уменьшается возможность допустить ошибку из-за незнания особенностей вешнего кода. 4.2 Повышается производительность на средне-малых, средних и больших проэктах т.к код становится проще и безопаснее. (На совсем малых проэктах в пару малых классов производительность программиста может упасть за счет "лишних действий", но по-факту, оно того все равно стоит) 4.3 Ну и в конце-концов, публичный метод — это обещание для пользователей. Каждо изменение (удаление, изменение сигнатуры, а иногда и добавление) открытого метода breaking change для клиентов, они должны пересмотреть код, который использует ваш класс Таким образом, вы не должны просто так, без особой на то необходимости менять открытые методы класса. А вот изменения в закрытых методах обычно происходят при рефакторинге в массовом порядке: методы упрощаются, объединяются, раскладываются на несколько, переносятся вверх-вниз по иерархии, меняется их семантика, и всё это никак не отражается на пользователях вашего класса. 5 Частные методы используют статическую привязку в Java, и они связываются во врем компиляции, которое быстро сравнивается с динамическим связыванием, которое происходит во время выполнения, а также дает JVM шанс либо встроить метод, либо оптимизировать его. 6 Присвоение переменных приватным в java и предоставление им getter и setter делае ваш класс совместимым с именованием бинов Java и другими структурами на основе отражения, такими как displaytag. 7 Если посмотреть на закрытый метод, вы наверняка знаете, что никто его не использует, что очень помогает при отладке java-программы. 8 Более удобные подсказки (когда ставишь точку и тебе предлогают выбрать метод/параметр) -- IDE не показывает ничего "лишнего"(только паблики) при использовании класса. IDE, например Netbeans, IDEA и Eclipse, используют эту информацию и автоматическ проверяют, используются ли частные методы внутри класса или нет, и могут отображать соответствующее предупреждение для улучшения качества кода или удаления неиспользуемых операторов, переменных или методов.

Ответ 9



Единственный чрезвычайно важный фактор, отличающий хорошо спроектированный модул от неудачного,- степень сокрытия его внутренних данных и иных деталей реализации о других модулей. Хорошо спроектированный модуль скрывает все детали реализации, четк разделяя свой АРI и реализацию. Модули взаимодействуют друг с другом только через свои API, и ни один из них не знает, какая обработка происходит внутри другого модуля. Эта концепция, называемая сокрытием информации (information hiding) или инкапсуляцией (encapsulatiori), представляет собой один из фундаментальных принципов разработки программного обеспечения. Сокрытие информации важно по многим причинам, большинство из которых Связано с те обстоятельством, что этот механизм эффективно изолирует друг от друга модули, составляющи систему, позволяя разрабатывать, тестировать, оптимизировать, использовать, исследоват и обновлять их по отдельности. Благодаря этому ускоряется разработка системы, так ка различные модули могут создаваться параллельно. Кроме того, уменьшаются расходы на сопровождени приложения, поскольку каждый модуль можно быстро изучить и отладить, минимально риску навредить остальным модулям. Само по себе сокрытие информации не может обеспечить хороше производительности, но оно создает условия для эффективного управления производительностью. Когда разработка системы завершена и процедура ее профилирования показала, работа каких модулей вызывает падение производительности, можно заняться их оптимизацией, не нарушая функционирования остальных модулей. Сокрытие информации повышает возможность повторного использования программ, поскольку каждый отдельно взятый модуль независим от остальных модулей и часто оказывается полезен в иных контекстах, чем тот, для которого он разрабатывался. Наконец, сокрытие информации уменьшает риски при построении больших систем: удачными могут оказаться отдельные модули, даже если в целом система не будет пользоваться успехом. Язык программирования java имеет множество возможностей для сокрытия информации Одна из них - механизм управления доступом (access control), задающий степень доступност (accessibility) для интерфейсов, классов и членов классов. Доступность любой сущности определяется тем, в каком месте она была декларирована и какие модификаторы доступа, если таковые есть, присутствуют в ее декларации (private, protected или public). Правильное использование этих модификаторов имеет большое значение для сокрытия информации. Главное правило заключается в том, что вы должны сделать каждый класс или член максимальн недоступным. Другими словами, вы должны использовать самый низший из возможных уровней доступа, который еще допускает правильное функционирование создаваемой программы. Для классов и интерфейсов верхнего уровня (не являющихся вложенными) существуют лиш два возможных уровня доступа: доступный только в пределах пакета (package-private) открытый (public). Если вы объявляете класс или интерфейс верхнего уровня с модификаторо public, он будет открытым, в противном случае он будет доступен только в пределах пакета Если класс или интерфейс верхнего уровня можно сделать доступным только в пакете, так и нужно поступать. При этом класс или интерфейс становится частью реализации этого пакета, а не частью его внешнего API. Вы можете модифицировать его, заменить или исключить из пакета, не опасаясь нанести вред клиентам. Если же вы делаете класс или интерфейс открытым, на вас возлагается обязанность всегда поддерживать его с целью сохранения совместимости. Если класс или интерфейс верхнего уровня, доступный лишь в пределах пакета, используетс только в одном классе, вы должны рассмотреть возможность превращения его в закрыты класс (или интерфейс), который будет вложен именно в тот класс, где он используется Тем самым вы еще более уменьшите его доступность. Однако это уже не так важно, как сделать необоснованно открытый класс доступным только в пределах пакета, поскольку класс, доступный лишь в пакете, уже является частью реализации этого пакета, а не его внешнего API. Для членов класса (полей, методов, вложенных классов и вложенных интерфейсов) существуют четыре возможных уровня доступа, которые перечислены здесь в порядке увеличения доступности: Закрытый (private) - данный член доступен лишь в пределах того класса верхнего уровня, где он был объявлен. Доступный лишь в пределах пакета (package-private) - член доступен из любого класса в пределах того пакета, где он был объявлен. Формально этот уровень называется доступом по умолчанию (default access), и именно этот уровень доступа вы получаете, если не -были указаны модификаторы доступа. Защищенный (protected) - член доступен для подклассов того класса, где этот член был объявлен (с небольшими ограничениями); доступ к члену можно получить из любого класса в пакете, где этот член был объявлен. Открытый (public) - член доступен отовсюду. После того как для вашего класса тщательно спроектирован открытый API, вам следуе сделать все остальные члены класса закрытыми. И только если другому классу из того ж пакета действительно необходим доступ к какому-то члену, вы можете убрать модификато private и сделать этот член доступным в пределах всего пакета. Если вы обнаружите, чт таких членов слишком много, еще раз проверьте модель вашей системы и попытайтесь найти другой вариант разбиения на классы, при котором они были бы лучше изолированы друг от друга. Как было сказано, и закрытый член, и член, доступный только в пределах пакета, являются частью реализации класса и обычно не оказывают воздействия на его внешний API. Однако они могут "просочиться" во внешний API, если класс реализует интерфейс Serializable. Если уровень доступа для члена открытого класса меняется с доступного в пакете н защищенный, уровень доступности данного члена резко возрастает. Для этого класса защищенны член является частью внешнего API, а потому ему навсегда должна быть обеспечена поддержка. Более того, наличие защищенного члена в классе, передаваемом за пределы пакета, представляет собой открытую передачу деталей реализации. Потребность в использовании защищенных членов должна возникать сравнительно редко. Существует одно правило, ограничивающее ваши возможности по уменьшению доступност методов. Если какой-либо метод переопределяет метод супер класса, то методу в подкласс не разрешается иметь более низкий уровень доступа, чем был у метода в суперклассе. Эт необходимо для гарантии того, что экземпляр подкласса можно будет использовать повсюду где можно было использовать экземпляр суперкласса. Если вы нарушите это правило, то когда попытаетесь скомпилировать этот подкласс, компилятор сгенерирует сообщение об ошибке. Частный случай правила: если класс реализует некий интерфейс, то все методы класса, представленные в этом интерфейсе, должны быть объявлены как открытые (public). Это объясняется тем, что в интерфейсе все методы неявно подразумеваются открытыми. Открытые поля (в отличие от открытых методов) в открытых классах должны быть редки явлением (если вообще должны ПОЯВЛЯТЬСЯ). Если поле не имеет модификатора final ил имеет модификатор и ссылается на изменяемый объект, то, делая его открытым, вы упускает возможность наложения ограничений на значения, которые могут быть записаны в этом поле Вы также лишаетесь возможности предпринимать какие-либо действия в ответ на изменение этого поля. Отсюда простой вывод: классы с открытыми изменяемыми полями небезопасны в системе с несколькими потоками (not thread-safe). Даже если поле имеет модификатор final и не ссылается на изменяемый объект, объявляя его открытым, вы отказываетесь от возможности гибкого перехода на новое представление внутренних данных, в котором это поле будет отсутствовать. Из правила, запрещающего открытым классам иметь открытые поля, есть одно исключение С помощью полей public static final классы могут предоставлять вовне константы. Согласн договоренности, названия таких полей состоят из прописных букв, слова в названии разделяютс символом подчеркивания. Крайне важно, чтобы эти поля содержали либо простые значения, либо ссылки на неизменяемые объекты. Поле с модификатором final, содержащее ссылку на изменяемый объект, обладает всеми недостатками поля без модификатора final: хотя саму ссылку изменить нельзя, объект, на который она указывает, может быть изменен - с роковыми последствиями. Заметим, что массив ненулевой длины всегда является изменяемым. Поэтому практическ никогда нельзя декларировать поле массива как public static final. Если в классе будет такое поле, клиенты получат возможность менять содержимое этого массива. Часто это является причиной появления дыр в системе безопасности. // Потенциальная дыра в системе безопасности public static final Туре[] VALUES = { ... } ; Открытый массив следует заменить закрытым массивом и открытым неизменяемым списком: private static final Туре[] PRIVATE_VALUES = { ... }; public static final List VALUES = Collections.unmodifiableList(Arrays.asList(PRIVATE_VALUES)); Другой способ: если на этапе компиляции вам необходима проверка типов и вы готов пожертвовать производительностью, то можете заменить открытое поле массива открытым методом, который возвращает копию закрытого массива. private static final Туре[] PRIVATE_VALUES = { .. . } ; private static final Туре[] values() { return ( Туре[] ) PRIVATE_VALUES.clone(); } Подведем итоги. Всегда следует снижать уровень доступа, насколько это возможно. Тщательн разработав наименьший открытый API, вы должны не дать возможности каким-либо случайны классам, интерфейсам и членам стать частью этого API. За исключением полей типа public static final, других открытых полей в открытом классе быть не должно. Убедитесь в том, что объекты, на которые есть ссылки в полях типа public static final, не являются изменяемыми. Источник: "Java. Эффективное программирование." Джошуа Блох.

Ответ 10



Первым принципом ООП является инкапсуляция. По сути, она означает возможность скрыт средствами языка несущественные детали реализации от пользователя объекта. Пользовател объекта приветствуют инкапсуляцию, поскольку этот принцип ООП позволяет упростить задачи программирования. Нет необходимости беспокоиться о многочисленных строках программного кода, который выполняет работу класса "за кулисами". Bсe, что требуется от вас, – это создание экземпляра и отправка подходящих сообщений. Одним из аспектов инкапсуляции является защита данных. В идеале данные состояни объекта должны определяться, как приватные. В этом случае "внешний мир" будет вынужден "смиренно просить" право на изменение или чтение соответствующих значений. (c) Троелсен

Ответ 11



Для тех, кому нужен быстрый ответ, без надобности углубляться сильно в инкапсуляцию. private методы и переменные видны только внутри класса. Их не видят никакие посторонние классы. Даже их дети. Это делают для предотвращения нежелательного изменения данных извне. Например, ты создаешь Аккаунт в банке, это будет наш объект. Ты не хочешь чтобы кого-нибудь извне была возможность сменить пароль или посмотреть, какой баланс у теб на счету, кроме тебя. Таким образом методы changePassword() и viewBalance() будут private. А метод типа viewProfile() для просмотра твоего профиля будет открыт для всех, т.е. public.

Комментариев нет:

Отправить комментарий