Я искал и знаю теоретическую разницу.
- public - любой класс / функция может получить доступ к методу / свойству.
- protected - только этот класс и любые подклассы могут иметь доступ к методу / свойству.
- private - только этот класс может получить доступ к методу / свойству. Это даже не будет унаследовано.
Это все хорошо, вопрос в том, какова практическая разница между ними? Когда бы вы использовали private
и когда вы бы использовали protected
? Есть ли стандартная или приемлемая хорошая практика по этому поводу?
До сих пор, чтобы сохранить концепцию наследования и полиморфизма, я использую public
все, к чему следует обращаться извне (например, конструкторы и функциональность основного класса), и protected
внутренние методы (логика, вспомогательные методы и т. Д.). Я на правильном пути?
(Обратите внимание, что этот вопрос для меня, но также и для дальнейшего использования, так как я не видел такой вопрос, как этот)
oop
language-agnostic
coding-style
Призрак Мадары
источник
источник
internal
в языке C #, который ограничивает уровень доступа класса или его членов в физической сборке. Хотя я не уверен насчет его поддержки или чего-то подобного в других языках.Ответы:
Нет, вы не на правильном пути. Хорошее практическое правило: сделайте все как можно более приватным. Это делает ваш класс более инкапсулированным и позволяет изменять внутреннее содержимое класса, не затрагивая код, использующий ваш класс.
Если вы разрабатываете свой класс как наследуемый, то тщательно выбирайте то, что может быть переопределено и доступно из подклассов, и сделайте это защищенным (и, наконец, поговорим о Java, если вы хотите сделать его доступным, но не перезаписываемым). Но имейте в виду, что, как только вы соглашаетесь иметь подклассы вашего класса и есть защищенное поле или метод, это поле или метод является частью общедоступного API класса и не может быть изменен позже без нарушения подклассов.
Класс, который не предназначен для наследования, должен быть окончательным (в Java). Вы можете ослабить некоторые правила доступа (от частного к защищенному, от финального до не финального) ради модульного тестирования, но затем задокументируйте его и дайте понять, что, хотя метод защищен, он не должен быть переопределен.
источник
private
противprotected
Когда я хочу это свойство наследуется, и когда не я? Я не могу точно сказать, хочет ли пользователь иногда в будущем взять мой класс и продлить его ...Позвольте мне предвосхитить это, сказав, что я говорю в первую очередь о доступе к методам здесь и, в несколько меньшей степени, отмечая классы как final, а не членский доступ.
Старая мудрость
Это имело смысл в те дни, когда оно было написано, до того, как открытый исходный код доминировал в пространстве библиотеки для разработчиков и в зависимости от VCS / mgmt. благодаря сотрудничеству с Github, Maven и т. д. стали сотрудничать друг с другом. Тогда еще можно было заработать, ограничивая способ (ы) использования библиотеки. Я провел, вероятно, первые 8 или 9 лет моей карьеры, строго придерживаясь этой «лучшей практики».
Сегодня я считаю, что это плохой совет. Иногда есть разумный аргумент для обозначения метода private или final класса, но он встречается крайне редко, и даже тогда он, вероятно, ничего не улучшает.
Вы когда-нибудь:
Вот три самых больших объяснения, которые я слышал о пометке методов private по умолчанию:
Рационализация № 1: это небезопасно и нет причин переопределять определенный метод
Я не могу сосчитать, сколько раз я ошибался в том, будет ли когда-либо необходимость переопределять определенный метод, который я написал. Проработав несколько популярных библиотек с открытым исходным кодом, я с трудом узнал истинную стоимость маркировки вещей частными. Это часто исключает единственное практическое решение непредвиденных проблем или вариантов использования. И наоборот, я никогда за более чем 16 лет профессионального развития не сожалел о том, что помечал метод, защищенный вместо частного, по причинам, связанным с безопасностью API. Когда разработчик решает расширить класс и переопределить метод, он сознательно говорит: «Я знаю, что я делаю». и ради производительности этого должно быть достаточно. период. Если это опасно, обратите внимание на класс / метод Javadocs, а не просто слепо захлопните дверь.
Методы маркировки, защищенные по умолчанию, - это смягчение одной из основных проблем в разработке современных ЕО: провал воображения.
Рационализация № 2: поддерживает чистоту публичного API / Javadocs
Это более разумно, и, в зависимости от целевой аудитории, это может быть даже правильным решением, но стоит подумать, какова стоимость поддержания чистоты API на самом деле: расширяемость. По причинам, указанным выше, вероятно, имеет смысл пометить объекты, защищенные по умолчанию, на всякий случай.
Рационализация № 3: Мое программное обеспечение является коммерческим, и мне нужно ограничить его использование.
Это тоже разумно, но, как потребитель, я бы каждый раз шел с менее строгим конкурентом (при условии, что существенных различий в качестве не существует).
Никогда не говори никогда
Я не говорю, никогда не отмечайте методы как частные. Я говорю, что лучшее эмпирическое правило - «защищать методы, если нет веских причин не делать этого».
Этот совет лучше всего подходит для тех, кто работает с библиотеками или крупномасштабными проектами, разбитыми на модули. Для небольших или более монолитных проектов это не имеет большого значения, так как вы все равно контролируете весь код, и легко изменить уровень доступа к коду, если / когда вам это нужно. Хотя и тогда я бы дал тот же совет :-)
источник
Rationalization # 1
- Когда я отмечаю что-то как защищенное, я решаю сделать это явно, поскольку я чувствую, что это поведение не является окончательным и может быть случаем, когда мои дочерние классы захотят переопределить это. Если я не уверен, тогда я бы хотел сделать его приватным по умолчанию. Специально для такого языка, как C #, который по умолчанию поддерживает метод, не являющийся виртуальным, добавление только защищенного спецификатора доступа не имеет смысла. Вы должны добавить оба словаvirtual
иprotected
ключевые слова, чтобы сделать ваше намерение очень ясным. Кроме того, люди предпочитают ассоциацию, а не наследование, такprotected
как дефолт трудно понятьХватит злоупотреблять приватными полями !!!
Кажется, что комментарии здесь в основном поддерживают использование частных полей. Ну, тогда я должен сказать что-то другое.
Частные поля хороши в принципе? Да. Но говорить, что золотое правило - делать все приватным, когда вы не уверены , определенно неправильно ! Вы не увидите проблемы, пока не столкнетесь с ней. На мой взгляд, вы должны пометить поля как защищенные, если вы не уверены .
Есть два случая, когда вы хотите расширить класс:
В первом случае нет ничего плохого в приватных полях. Тот факт, что люди злоупотребляют частным полями, очень расстраивает, когда вы узнаете, что вы не можете изменить дерьмо.
Рассмотрим простую библиотеку, которая моделирует автомобили:
Автор библиотеки подумал: нет причин, по которым пользователям моей библиотеки нужен доступ к деталям реализации,
assembleCar()
верно? Давайте отметим винт как частный.Ну, автор не прав. Если вы хотите изменить только
assembleCar()
метод, не копируя весь класс в ваш пакет, вам не повезло. Вы должны переписать свой собственныйscrew
поле. Допустим, в этой машине используется дюжина винтов, и каждый из них включает в себя некоторый нетривиальный код инициализации в различных частных методах, и все эти винты помечены как частные. В этот момент он начинает сосать.Да, вы можете поспорить со мной, что автор библиотеки мог бы написать лучший код, так что с частными полями все в порядке . Я не спорю, что частное поле является проблемой с ООП . Это проблема, когда люди их используют.
Мораль этой истории в том, что если вы пишете библиотеку, вы никогда не знаете, хотят ли ваши пользователи получить доступ к определенному полю. Если вы не уверены, отметьте это,
protected
чтобы все были счастливы позже. По крайней мере, не злоупотребляйте приватным полем .Я очень поддерживаю ответ Ника.
источник
Недавно я прочитал статью, в которой говорилось о максимально возможной блокировке каждого класса. Сделайте все окончательно и приватно, если только у вас нет срочной необходимости предоставлять какие-либо данные или функциональные возможности внешнему миру. В дальнейшем всегда легко расширить область видимости, чтобы сделать ее более допустимой, но не наоборот. Сначала подумайте о том, чтобы сделать как можно больше вещей
final
, которые сделают выбор междуprivate
иprotected
намного проще.Теперь, если у вас остался последний класс, тогда сделайте все приватным, если что-то абсолютно не нужно миру - сделайте это публичным.
Если у вас есть класс, у которого есть подкласс (ы), то внимательно изучите каждое свойство и метод. Сначала рассмотрите, хотите ли вы даже предоставить это свойство / метод подклассам. Если вы это сделаете, то подумайте, может ли подкласс нанести ущерб вашему объекту, если он испортил значение свойства или реализацию метода в процессе переопределения. Если это возможно, и вы хотите защитить свойство / метод вашего класса даже от подклассов (звучит иронично, я знаю), то сделайте его закрытым. В противном случае сделайте это защищенным.
Отказ от ответственности: я не много программирую на Java :)
источник
final class
в Java это класс, который не может быть унаследован от. A неfinal method
является виртуальным, то есть не может быть переопределено подклассом (методы Java по умолчанию являются виртуальными). Afinal field/parameter/variable
является ссылкой на неизменяемую переменную (в том смысле, что ее нельзя изменить после инициализации).Когда бы вы использовали
private
и когда вы бы использовалиprotected
?Частное наследование может рассматриваться как реализованное с точки зрения отношений, а не отношений IS-A . Проще говоря, внешний интерфейс наследующего класса не имеет (видимой) связи с наследуемым классом. Он использует
private
наследование только для реализации аналогичной функциональности, которую обеспечивает базовый класс.В отличие от частного наследования, защищенное наследование является ограниченной формой наследования, в которой производный класс IS-A является разновидностью базового класса, и он хочет ограничить доступ производных членов только к производному классу.
источник
Ну, все дело в инкапсуляции, если классы платежной ведомости обрабатывают выставление счета за платеж, тогда как в классе продукта зачем нужен весь процесс биллинга, т.е. не что иное, как общедоступный для тех, где другие классы тоже будут использовать, защищенный для этих ограничений только для расширения классов. Поскольку вы - мадара учиха, то
"limboo"
вы можете видеть это как частное лицо (вы учитесь только в одном классе).источник