2014-10-29 3 views
0

Я вхожу в введение в класс Java, и я делал немного исследований по переменным. Кажется, что знающие программисты заявляют, что плохой практикой является определение переменных в публичной видимости. Я вижу, что они говорят, что это плохая практика, но я не могу найти рифму или причину их претензий. Вот как я определил свои переменные в приложении для моего курса.Почему переменная общедоступная видимость является плохой практикой

public class DykhoffWk3Calculator 
    { 
     /* 
     * This class is used to define the variables in a static form so all 
     * classes can access them. 
     */ 
     public static double commissionRate = .03, startSalary = 45000, 
       accelerationFactor = 1.25; 
     public static double annualSales, commissionTotal, totalCompensation, 
       total, count, count2; 
     private static Object input; Object keyboard; 

public static class UserInput 
    { //Then continue with my other classes 

Я думал, что это был логический метод определения их, чтобы все классы, а не только основные, могли обращаться к ним. Может кто-нибудь объяснить мне, почему это плохая практика, и где переменные должны быть определены? Будем очень благодарны любой помощи.

+0

Общественная видимость, а не «в открытом классе». –

+0

Переменные должны инициализироваться/создаваться только в их репликативной области - поскольку они используют память и поэтому используют больше памяти, чем требуется. – jbutler483

+0

Theire - это разница между «переменной в публичном классе» и «открытой переменной в классе» – jhamon

ответ

4

Вкратце: поскольку вся ваша общественная «площадь поверхности» для класса эффективно определяет его API.

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

Я думал, что это был логический метод их определения, поэтому все классы, а не только основные, могли получить к ним доступ.

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

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

В целом, сокращение «площади поверхности» классов является действительно хорошим вещь которую нужно сделать. Ограничение того, как другие классы могут взаимодействовать с этим, упрощает управление и понимание отношений, а также упрощает внутренние изменения, невидимые для других классов. Подумайте, что этот класс делает, что он будет предоставлять другим классам, определяя интерфейс (будь то фактический interface или нет). И выставлять только другие классы, минимальный минимум, необходимый для выполнения этих требований.

И это никогда не подразумевает возможность произвольного доступа к переменным.

+0

Я думаю, вам нужно упомянуть, что решение не иметь публичных полей - это предоставление геттеров и сеттеров. – dkatzel

+0

Спасибо за ответ! Вы действительно помогли мне понять, почему это нехорошо. Теперь я понимаю, что внешние объекты могут изменять эти переменные, даже если вы их не намеревались. Еще раз спасибо! –

+1

@dkatzel Я бы даже не был таким предписывающим. Как я упоминал ближе к концу, нужно подумать о том, какие концептуальные операции/функции вы хотите предоставить этому классу, а затем делать все, что необходимо для их обеспечения. Поэтому, если имеет смысл разоблачить какое-либо свойство через геттер, тогда вы должны определить геттер. Но я не думаю, что нужно делать это волей-неволей, если это действительно не нужно. –

0

Публичные переменные вообще в классе - плохая идея. Так как это означает, что другие классы/программы могут изменять состояние экземпляров.

Поскольку для защиты своего состояния класс защиты и его состояние «согласованы», его можно обеспечить, определяя публичные сеттеры (поскольку это позволяет запускать код для проверки/восстановления состояния).

Установив переменные public, состояние не защищено. Если позже не все представимые состояния являются допустимыми состояниями, возникает проблема.

Пример:

Допустим, вы хотите реализовать ArrayList<T>, то он будет выглядеть (не в полном объеме):

public class ArrayList<T> { 

    public int size = 0; 
    public Object[] data = new Object[5]; 

} 

Теперь можно изменить size в ArrayList. Без добавления элемента. Теперь, если вы попросите экземпляр ArrayList<T> удалить/добавить/скопировать/... что угодно, данные, на которых он работает, могут быть неправильными.

Возможно, вы можете утверждать, что программист хорош: он не будет изменять объект, если только ему не нужно и в соответствии с «правилами». Но такие вещи в конечном итоге всегда идут не так, и что если вы решите изменить свое определение ArrayList (например, используя два int для size). В этом случае вам нужно будет переписать весь код, который устанавливает такие поля.

В заключение: private/protected изобретен для защиты класса экземпляра от других экземпляров, которые превратят экземпляр коррумпированы/недействительно/несовместимыми/...

+0

Спасибо! Это действительно помогло. –

1

Таким образом, общая точка является то, что вы на самом деле DON «Мне нужно, чтобы кто-нибудь мог получить доступ к этим значениям. Я не только вижу эти переменные, но и могу изменить их на все, что мне нравится. Это может привести к проблемам в более крупных и более сложных программах.

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

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

+0

Спасибо! Это действительно помогло. –

0

Во-первых, вы заявляете это неправильно.

его плохое, чтобы сделать вашу переменную общедоступной i.e: public String name = null; это плохо. Вы всегда должны сделать это как private String name = null;

Чтобы понять, почему, вам нужно копать немного в идеологию Упс OPPS идеология утверждает, что каждый объект вашего класса будет иметь 2 вещи:

  • Свойства: то, что мы также называем переменными или состоянием.
  • Поведение: то, что мы называем методами или функциями.

Свойства идентифицируют объект в течение определенного периода времени. Поведение позволяет управлять свойствами объекта, так что один и тот же объект с течением времени может отображаться в разных состояниях. Org: объект продукта за период может быть «Доступной позицией» или «Добавлен в корзину» или «Добавить в корзину», Продано "или" Нет в наличии "в зависимости от его состояния. Поскольку состояние критически важно для объекта, поэтому объект не должен допускать операции прямой бессмысленной мутации в его состоянии.Объекты должны сохранять для них свои переменные и раскрывать поведение, которое внешний мир может использовать для взаимодействия с объектом и изменения состояния на основе операции, выполняемой в поведении. например: вызывать поведение addToCart() на объекте Product, которое было в состоянии «Доступная позиция», вероятно, означало бы: изменение не только его состояния на «добавлено в корзину», но, вероятно, заставляя других пользователей знать, что количество этих продуктов теперь доступно на 1 меньше.

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

+0

Спасибо! Это действительно помогло. –

0

По Конвенции Поля, методы и конструкторы, объявленные публичными (наименее ограничительными) в рамках открытого класса, видны для любого класса в программе Java, независимо от того, находятся ли эти классы в одном пакете или в другом пакете. Это означает, что изменение в значение поля, безусловно, повлияет на другие классы, получающие доступ к этому полю. Это разрушает весь смысл инкапсуляции.

Смежные вопросы