Разве поля в классах не похожи на глобальные переменные?

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

Из того, что я слышал, использование глобальных переменных в таких языках программирования, как C, - плохая идея. А как насчет полей класса Java, разве они не являются чем-то вроде глобальных переменных для всех методов вашего класса? Разве использование полей — плохая идея? (Или, может быть, я что-то не так понял или программирую на "неправильном" языке Java)


person Marin Bauer    schedule 29.11.2010    source источник


Ответы (5)


Я предполагаю, что под «переменными класса» вы подразумеваете «статические переменные».

Вы спросите: «Разве они не являются чем-то вроде глобальных переменных для всех ваших методов класса?».

Да, ты прав. Внутри класса они ведут себя как глобалы со всеми их проблемами.

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

Также в некоторых ситуациях имеет смысл иметь все экземпляры класса совместно использующие переменную (например, синглтон). Вы просто должны использовать его ответственно.

Вы не должны их использовать?
Нет, вы можете их использовать. Но ограничьте их видимость до необходимого минимума, чтобы они не стали «де-факто» глобальными.
Также сделайте их окончательными, если это возможно.

person zockman    schedule 29.11.2010
comment
Я имею в виду нестатические переменные. Со статическими переменными все еще хуже, потому что вы не можете сказать, какой объект читает/записывает какую переменную. Я думал, что глобальные переменные вообще плохи, не только в целых программах, но и в файле кода на 2000 строк, разве это не плохо? Разве вы не знаете о файлах классов с более чем 2000 строками кода? (Думаю, в реальных системах определенно будут большие классы) - person Marin Bauer; 29.11.2010

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

person fastcodejava    schedule 29.11.2010
comment
Я вижу, что это один из основных факторов, усложняющих поддержку кода. Я хотел бы найти больше сообщений в блогах / эссе, выступающих против этого, потому что мне не помешала бы некоторая помощь в том, чтобы сформулировать, насколько большой проблемой это часто является. Сигнатуры методов, такие как void TakeCareOfStuff() {}, являются огромным запахом кода. - person ; 01.05.2012

Я бы сказал, что вы не совсем понимаете, как работает Java (или любой другой объектно-ориентированный язык).

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

У вас будет класс Car, и вы создадите новый объект (новый экземпляр) класса Car для представления каждой новой машины, которая вам нужна. Сам автомобиль состоит из разных компонентов, у вас есть колеса, двигатель, окна и т. д. Таким образом, у вас будут классы для каждого из этих компонентов, и каждый объект автомобиля будет содержать свой собственный набор объектов из всех разных классов, то есть:

Car1 {
       motor1
       window1.1, window1.2
       wheel1.1,wheel1.2
}

Car2 {
       motor2
       window2.1, window2.2
       wheel2.1,wheel2.2
}

В этом случае вы должны определить каждый из компонентов автомобилей как поля класса. Эти поля для всех эффектов являются «глобальными» в том смысле, что к ним можно получить доступ из любого метода этого класса. Деталь, которую вы, кажется, упускаете, заключается в том, что каждый новый объект этого класса имеет свой собственный набор полей и методов. Они не разделяют их, поэтому каждый мотор, комплект колес и т. д. принадлежит одному экземпляру класса Car. Итак, если в классе автомобиля у вас есть метод с именем, скажем, deleteWindows(), который избавится от всех окон, и вы вызвали этот метод для автомобиля2, это не приведет к удалению окон автомобиля1.

Еще одна важная деталь заключается в том, что вы можете определить эти переменные с помощью нескольких «префиксов» (методов тоже). Во-первых, у вас есть общедоступные и частные (защищенные, но я не буду вдаваться в подробности). Объявляя переменную как приватную, вы говорите, что единственный объект, который может получить доступ к этой переменной и изменить ее, — это тот, кто ею владеет. С другой стороны, общедоступная переменная может быть доступна и изменена любым другим объектом. Они доступны, но вы должны явно сказать, что хотите изменить переменную этого объекта (написав имя_объекта.variable, в нашем случае car1.motor).

Вы также можете иметь переменные/методы, которые являются общими для всех экземпляров класса. Для этого вы объявляете их как статические (они фактически принадлежат классу, а не какому-либо объекту этого класса в частности). Private/public по-прежнему применяются, частная статическая переменная доступна только экземплярам этого класса (и статическим методам того же класса), а общедоступные доступны любому другому классу/объекту. Чтобы получить к ним доступ извне класса, к которому они принадлежат, вы используете ClassName.variable/method (то есть Car.variable в предыдущем примере).

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

Надеюсь, я развеял ваши сомнения. В любом случае, я бы посоветовал вам немного почитать об объектно-ориентированном программировании, возможно, получить книгу, которая учит Java с большим первоначальным акцентом на объектную ориентацию (ОО), поскольку, хотя это не сложная концепция для понимания, это может быть трудно привыкнуть к этому и правильно программировать на языке OO, если вы пришли из не-OO.

Возможно, вы захотите изучить BlueJ. Это Java IDE, которая в основном заставляет вас понимать и использовать объектно-ориентированное программирование. Это не то, что я предлагаю использовать слишком долго, но это может быть хорошим местом для начала, пока вы хорошо не разберетесь в основах объектно-ориентированного программирования.

Цепи

person Zepee    schedule 29.11.2010
comment
Я знаю разницу между статическими и нестатическими полями и знаю, что каждый объект имеет свое собственное состояние. Позвольте мне сказать иначе. Допустим, у вас есть 2000 строк кода C в файле, который в основном представляет собой множество функций, хорошо ли иметь в этом файле глобальные переменные, которые будут использовать эти функции? Насколько я знаю, ответ - нет (поскольку вы не знаете, какие функции пишут/читают каждую глобальную переменную). То же самое происходит с классами, класс может иметь 2000 строк кода, в этой области класса поля подобны глобальным переменным. Верно? Разве это не плохо, как пример с кодом C? - person Marin Bauer; 29.11.2010
comment
У меня не так много опыта вне языков OO, но кажется, что проблема, на которую вы указываете, заключается в том, что я не знаю, что изменяется, что относится к общедоступным переменным. Вы должны беспокоиться о том, какие объекты могут напрямую обращаться к вашим переменным и изменять их. Это один из основных принципов ООП, инкапсуляция, который гласит, что объекты/классы должны знать только то, что все остальное делает, но не КАК они это делают. Таким образом, обычная практика делать поля закрытыми и предоставлять геттеры/сеттеры только тогда, когда каждый объект может контролировать, насколько он прозрачен для внешнего мира. - person Zepee; 30.11.2010
comment
Однако внутри каждого класса вам нужна полная прозрачность. Как хорошо, что ты существуешь, если даже ты не знаешь, как ты выглядишь? Другими словами, как бы вы отличили объект A от объекта B без переменных класса? Вам не следует беспокоиться о том, что в вашем объекте есть несколько методов, обращающихся к его полям, а есть только другие объекты, обращающиеся к его полям. Переменные класса не только не плохи, поскольку они необходимы, они определяют объект, и возможность иметь несколько экземпляров класса, каждый со своим собственным набором атрибутов, — это именно то, почему языки OO были созданы в первую очередь. - person Zepee; 30.11.2010

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

Глобальные переменные доступны из любой области. Они, как правило, доступны для записи из любой области. Это затрудняет понимание и отладку больших кодовых баз. Глобальные переменные также провоцируют конфликты имен.

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

person Andy Thomas    schedule 29.11.2010

Но в Java вся программа не написана с использованием одного класса. И именно константы (публичные статические конечные поля) похожи на глобальные переменные. И мой совет вам не концентрироваться на каждой из этих отдельных частей java, что хорошего в java, так это то, что она дает в целом. Потому что именно тогда вы увидите важность каждой из этих функций java.

person asela38    schedule 29.11.2010