Подтвердить что ты не робот

Почему важна значимость видимости для методов и атрибутов?

Почему не следует оставлять все методы и атрибуты доступными из любого места (т.е. public)?

Можете ли вы дать мне пример проблемы, с которой я могу столкнуться, если я объявил атрибут как public?

4b9b3361

Ответ 1

Подумайте о сфере видимости как о внутренних кругах доверия.

Возьмите себя в качестве примера и подумайте о том, какие действия являются общедоступными, а какие - частными или защищенными. Есть много вещей, которые вы не делегируете никому, кто сделает от вашего имени. Есть некоторые, которые отлично подходят для запуска, и есть некоторые с ограниченным доступом.

Аналогично, в программировании области предоставляют инструменты для создания разных кругов доверия. Кроме того, делая вещи конфиденциальными/защищенными, дайте вам больше контроля над тем, что происходит. Например, вы можете разрешить сторонние плагины, которые могут расширить часть вашего кода, в то время как их можно ограничить тем, насколько далеко они могут идти.

Итак, чтобы обобщить, области обеспечивают вам дополнительный уровень безопасности и упрощают организацию, что они будут в противном случае.

Ответ 2

Подумайте о Макдональде как об объекте. Там хорошо известный публичный метод заказа BigMac.

Внутри будет еще несколько звонков, чтобы на самом деле ПОЛУЧИТЬ материалы для создания этого Bigmac. Они не хотят, чтобы вы знали, как работает их цепочка поставок, поэтому все, что вы получаете, это публичный вызов Gimme_a_BigMac() и никогда не позволит вам получить доступ к методам Slaughter_a_cow() или Buy_potatoes_for_fries().

Для вашего собственного кода, который никто никогда не увидит, продолжайте и оставите все публичным. Но если вы делаете библиотеку для повторного использования другими пользователями, тогда вы идете и защищаете внутренние детали. Это оставляет McDonald свободным, чтобы переключиться на то, что луч Скотти над патти, а не вызвать компанию-перевозчика для доставки мяса по суше. Конечный пользователь никогда не знает разницы - они просто получают свой BigMac. Но внутренне все могло кардинально измениться.

Ответ 3

Почему не следует оставлять все методы и атрибуты доступными из любого места (т.е. public)?

Потому что это слишком дорого.

Каждый публичный метод, который я делаю, должен быть тщательно разработан, а затем одобрен командой архитекторов, он должен быть реализован, чтобы быть надежным перед лицом произвольно враждебных или ошибочных вызывающих абонентов, он должен быть полностью протестирован, все проблемы, обнаруженные во время тестирования, должны иметь регрессионные пакеты добавлен, метод должен быть документирован, документация должна быть переведена не менее чем на двенадцать разных языков.

Самая большая стоимость всего: метод должен поддерживаться, без изменений, навсегда и всегда, amen. Если в следующей версии я решил, что мне не нравится, что сделал этот метод, я не могу его изменить, потому что теперь клиенты полагаются на него. Нарушение обратной совместимости общедоступного метода налагает затраты на пользователей, и я не хочу этого делать. Жизнь с плохим дизайном или реализация публичного метода накладывает большие затраты на дизайнеров, тестеров и разработчиков следующей версии.

Общественный метод может стоить тысячи или даже десятки тысяч долларов. Сделайте сотню из них в классе и там класс в миллион долларов.

Частные методы не имеют такой стоимости. Разумно потратить деньги акционеров; сделайте все частным, что вы, возможно, сможете.

Ответ 4

Поскольку это нарушает концепцию encapsulation, ключевой принцип ООП.

Ответ 5

Вероятно, вы рискуете?

<?php

class Foo
{
    /**
     * @var SomeObject
     */
    public $bar;
}

В вашем коде указано, что $bar должен содержать экземпляр объекта SomeObject. Однако любой, кто использует ваш код, мог бы

$myFoo->bar = new SomeOtherObject();

... и любой код, полагающийся на Foo:: $bar, будет SomeObject сломаться. С помощью геттеров и сеттеров и защищенных свойств вы можете выполнить это ожидание:

<?php

class Foo
{
    /**
     * @var SomeObject
     */
    protected $bar;

    public function setBar(SomeObject $bar)
    {
        $this->bar = $bar;
    }
}

Теперь вы можете быть уверены, что в любое время Foo:: $bar задано, будет с экземпляром объекта SomeObject.

Ответ 6

Скрывая детали реализации, он также предотвращает попадание объекта в несогласованное состояние.

Вот надуманный пример стека (псевдокод).

public class Stack {

  public List stack = new List();
  public int currentStackPosition = 0;

  public String pop() {
    if (currentStackPosition-1 >= 0) {
      currentStackPosition--;
      return stack.remove(currentStackPosition + 1);
    } else {
      return null;
    }
  }

  public void push(String value) {
    currentStackPosition++;
    stack.add(value);
  }
}

Если вы делаете обе переменные приватными, выполнение выполняется нормально. Но если public вы можете легко сломать его, просто установив неверное значение для currentStackPosition или непосредственно изменив список.

Если вы только раскрываете функции, которые вы предоставляете надежный контракт, который другие могут использовать и доверять. Развертывание реализации просто заставляет его работать, и никто не может с ним поработать.

Ответ 7

Инкапсуляция не нужна ни на одном языке, но она полезна. Инкапсуляция используется для минимизации числа потенциальных зависимостей с наибольшей вероятностью распространения изменений и помогает предотвратить несоответствия:

Простой пример: Предположим, что мы создали класс Rectangle, содержащий четыре переменные - длину, ширину, площадь, периметр. Обратите внимание, что площадь и периметр производятся по длине и ширине (обычно я бы не делал для них переменных), так что изменение длины изменило бы как площадь, так и периметр.

Если вы не использовали правильное скрытие информации (инкапсуляция), то другая программа, использующая этот класс Rectangle, могла бы изменять длину без изменения области, и у вас был бы непоследовательный Rectangle. Без инкапсуляции можно было бы создать прямоугольник длиной 1 и шириной 3 и иметь площадь 32345.

Используя инкапсуляцию, мы можем создать функцию, которая, если бы программа хотела изменить длину прямоугольника, чтобы объект соответствующим образом обновил свою область и периметр, не будучи непоследовательным.

Инкапсуляция устраняет возможности для несогласованности и переносит ответственность за постоянство на сам объект, а не на его использование.

Однако в то же время инкапсуляция иногда представляет собой плохую идею, а планирование движения и коллизия (в игровом программировании) - это области, где это особенно вероятно.

проблема заключается в том, что инкапсуляция является фантастической в ​​тех местах, где она необходима, но она ужасна при применении в тех местах, где она не нужна, например, когда есть глобальные свойства, которые должны поддерживаться группой инкапсуляции. Поскольку принудительная инкапсуляция OOP несмотря ни на что, вы застряли. Например, существует множество свойств объектов, которые являются нелокальными, например, любой глобальной согласованности. То, что имеет тенденцию происходить в ООП, состоит в том, что каждый объект должен кодировать свое представление о состоянии глобальной согласованности и делать свою часть, чтобы помочь поддерживать правильные глобальные свойства. Это может быть интересно, если вам действительно нужна инкапсуляция, чтобы позволить альтернативные реализации. Но если вам это не нужно, вы в конечном итоге пишете очень сложный код в нескольких местах, что в основном делает то же самое. Все кажется инкапсулированным, но на самом деле полностью взаимозависимым.

Ответ 8

Ну, на самом деле вы можете иметь все публичное, и он не нарушает инкапсуляцию, когда вы четко заявляете, что такое контракт, правильный способ использования объектов. Может быть, не атрибуты, но методы часто более скрыты, чем они должны быть.

Помните, что вы не дизайнер API, который нарушает инкапсуляцию, делая вещи общедоступными. Это пользователи этого класса могут сделать это, вызвав внутренние методы в своем приложении. Вы можете либо похлопать их по рукам, пытаясь сделать это (т.е. Объявить методы закрытыми), либо передать им ответственность (например, путем префикса не-API-методов с помощью "_" ). Вас действительно волнует, нарушает ли кто-то его код, используя вашу библиотеку по-другому, как вы ему советуете? Я этого не делаю.

Сделать практически все частное или окончательное - или оставить их без документации API, с другой стороны - это способ обескураживать расширяемость и обратную связь в open source. Ваш код можно использовать так, как вы даже не думали, что может быть не так, когда все заблокировано (например, методы с закрытыми по умолчанию на С#).

Ответ 9

Единственная проблема, с которой вы можете столкнуться, заключается в том, что люди будут видеть вас как "uncool", если вы не используете Закрытый или Защищенный или Абстрактный статический финал Интерфейс или что-то еще. Этот материал похож на дизайнерскую одежду или гаджеты Apple - люди покупают их не потому, что им нужно, а просто для того, чтобы не отставать от других.

Да, инкапсуляция - важная теоретическая концепция, но в практике "private" и друзья редко имеют смысл. Они могут иметь некоторый смысл в Java или С#, но на языке сценариев, например PHP с использованием "private" или "protected", это просто глупо, потому что инкапсуляция изобретена для проверки компилятором, которого нет в PHP. Подробнее.

См. также этот отличный ответ и @troelskn и @mario комментируют здесь

Ответ 10

Видимость - это просто то, что вы можете использовать для своего собственного, чтобы не нарушать собственный код. И если вы правильно его используете, вы поможете другим (кто использует ваш код), которые не нарушают собственный код (не используя правильный код).

Самый простой, широко известный пример, на мой взгляд, - это шаблон Singleton. Это образец, потому что это общая проблема. (Определение шаблона из Википедии:

является формальным способом документирования решения проблемы проектирования

Определение шаблона Singleton в Википедии:

В разработке программного обеспечения одноэлементный шаблон представляет собой шаблон проектирования, используемый для реализации математической концепции одноэлемента, путем ограничения экземпляра класса на один объект. Это полезно, когда необходим один объект для координации действий в системе.

http://en.wikipedia.org/wiki/Singleton_pattern

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

Ответ 11

Вы можете подумать, что предыдущие ответы являются "теоретическими", если вы используете свойства public в Doctrine2 Entities, вы ломаете ленивую загрузку.

Ответ 12

Чтобы спасти вас от себя!

Было несколько отличных ответов выше, но я хотел добавить немного. Это называется принцип наименьших привилегий. Чем меньше привилегий, тем меньше организаций имеют право нарушать вещи. Ломать все плохо.

Если вы следуете принципу наименьших привилегий, принцип наименьшего знания (или Закон Деметры) и принцип единой ответственности не отстает. Поскольку ваш класс, который вы написали, чтобы загрузить последние футбольные баллы, следовали этому принципу, и вы должны опросить его данные, а не просто сбрасывать прямо на ваш интерфейс, вы копируете и вставляете весь класс в свой следующий проект, экономя время разработки. Экономия времени разработки хорошая.

Если вам повезет, вы вернетесь к этому коду через 6 месяцев, чтобы исправить небольшую ошибку после того, как вы сделали gigaquads денег от него. Будущее "я" будет напрасно направлять свое собственное имя за то, что оно не соблюдает вышеуказанные принципы, и он станет жертвой нарушения принципа наименьшего удивления . То есть, ваша ошибка является ошибкой разбора в модели оценки футбола, но, поскольку вы не следовали LOD и SRP, вы удивлены тем фактом, что вы выполняете синтаксический анализ XML в соответствии с вашим производством. Есть намного лучшие вещи в жизни, чтобы удивляться, чем ужасность вашего собственного кода. Поверьте мне, я знаю.

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