Когда использовать переменную экземпляра объекта вместо передачи аргумента методу


93

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

Я предпочитаю хранить переменные экземпляра в списке в конце класса, но этот список становится длиннее по мере роста моей программы. Я полагаю, что если переменная передается достаточно часто, она должна быть видна всем методам, которые в ней нуждаются, но тогда я задаюсь вопросом: «Если все будет общедоступным, то вообще не нужно будет ничего передавать!»


1
Если у вас есть конкретные примеры, вы можете получить более полезные ответы,
brabster

Ответы:


55

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

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

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

  • Область действия переменной экземпляра предназначена не только для обеспечения безопасности, но и для инкапсуляции. Не думайте, что «целью должно быть сохранение приватности всех переменных». В случаях наследования хорошей альтернативой обычно является создание защищенных переменных. Вместо того, чтобы помечать все данные экземпляра как общедоступные, вы создаете геттеры / сеттеры для тех, к которым требуется доступ для внешнего мира. Не делайте их все доступными - только те, которые вам нужны. Это будет происходить на протяжении всего жизненного цикла разработки - об этом трудно догадаться с самого начала.

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


Мой ответ - добавить этот ответ к ответу H-Man2 (время жизни). Он должен быть атрибутом-членом тогда и только тогда, когда это постоянное состояние объекта. То есть значение имеет смысл само по себе за пределами области действия текущего стека методов.
Дэвид Родригес - дрибес

1
Моя внутренняя реакция - согласиться с Дэвидом и H-MAn2. Однако я читаю «чистый код» Роберта Мартина, и в главе 3 он реорганизует код, чтобы переместить что-то из параметра метода в переменную-член, потому что наличие большого количества параметров - это плохо. В целом, я предполагаю, что если ваш класс несет только одну ответственность, тогда время жизни объекта такое же, как время жизни этого вычисления, поэтому, возможно, фактический ответ заключается в том, что если вам нужно задать этот вопрос, то ваш класс слишком велик?
Энди

@ DavidRodríguez-dribeas, что вы имеете в виду под стеком методов?
совершиландройдер

@committedandroider: если значение переживает текущий вызов функции
Дэвид Родригес - dribeas

46

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

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


21

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

Вот пример:

myCircle = myDrawing.drawCircle(center, radius);

Теперь давайте представим, что класс myDrawing использует 15 вспомогательных функций для создания объекта myCircle, и для каждой из этих функций потребуется центр и радиус. Их по-прежнему нельзя устанавливать как переменные экземпляра класса myDrawing. Потому что они больше никогда не понадобятся.

С другой стороны, класс myCircle должен будет хранить как центр, так и радиус как переменные экземпляра.

myCircle.move(newCenter);
myCircle.resize(newRadius);

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

По сути, переменные экземпляра - это способ сохранить «состояние» объекта. Если переменная не обязательна, чтобы знать состояние объекта, она не должна быть переменной экземпляра.

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


Вы можете просто определить перемещение, чтобы использовать параметры (oldCenter, newCenter).
obesechicken13

4

ПО МОЕМУ МНЕНИЮ:

Если переменная является частью состояния экземпляра, то это должна быть переменная экземпляра - classinstance HAS-A instancevariable.

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

Надеюсь, это поможет


3

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

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

Также подумайте о безопасности, переменная открытого класса восприимчива к нежелательным изменениям из «внешнего» кода. Ваша основная цель должна заключаться в том, чтобы все переменные оставались закрытыми, а любая переменная, которая не является таковой, должна иметь очень вескую причину для этого.

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

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


Вы часто хотите, чтобы методы были общедоступными, чтобы вы могли их тестировать.
obesechicken13
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.