Все объекты гарантированно имеют метод .equals()
, поскольку Object содержит метод, .equals()
, который возвращает логическое значение. Задача подкласса переопределять этот метод, если требуется дополнительное определение определения. Без него (т. Е. С помощью ==
) только адреса памяти проверяются между двумя объектами для равенства. String переопределяет этот метод .equals()
и вместо использования адреса памяти возвращает сравнение строк на уровне символа для равенства.
Ключевое замечание состоит в том, что строки хранятся в одном пуле, поэтому после создания строки он всегда хранится в программе по тому же адресу. Строки не меняются, они неизменяемы. Вот почему это плохая идея использовать регулярную конкатенацию строк, если у вас есть серьезное количество обработки строк. Вместо этого вы будете использовать предоставленные классы StringBuilder
. Помните, что указатели на эту строку могут измениться, и если вам было интересно увидеть, были ли два указателя одинаковыми ==
, это был бы прекрасный способ. Строки сами не делают.
На самом деле существует множество веских причин , чтобы рассмотреть возможность использования аксессуаров, а не непосредственно подвергать поля класса - помимо аргумента инкапсуляции и облегчения будущих изменений.
Вот некоторые из причин, о которых я знаю:
Вы должны использовать геттеры и сеттеры, когда:
Так что это очень редко общий вопрос ОО; это вопрос, специфичный для языка, с разными ответами на разные языки (и различные варианты использования).
С точки зрения теории OO геттеры и сеттеры бесполезны. Интерфейс вашего класса - это то, что он делает, а не то, что его состояние. (Если нет, вы написали неправильный класс.) В очень простых случаях, когда то, что делает класс, просто, например, представляет точку в прямоугольных координатах, * атрибуты являются частью интерфейса; геттеры и сеттеры просто облака, что.
Путь другой: если вы считаете, что потребители вашего класса не должны даже знать, что у вас есть spam
, а тем более быть способным изменить его волей-неволей, а затем дать им метод set_spam
- это последнее, что вы хотите сделать.
* Даже для этого простого класса вы можете не обязательно хотите разрешить установку значений x
и y
. Если это действительно класс, не должны ли он иметь такие методы, как translate
, rotate
и т. Д.? Если это только класс, потому что ваш язык не имеет записей / structs / named tuples, тогда на самом деле это не вопрос OO ...
Но никто никогда не делает общий дизайн OO. Они выполняют дизайн и реализацию на определенном языке. И на некоторых языках геттеры и сеттеры далеки от бесполезности.
Если ваш язык не имеет свойств, то единственный способ представить что-то, что является концептуально атрибутом, но на самом деле вычисляется или проверяется и т. Д. ., находится через геттеры и сеттеры.
Даже если ваш язык имеет свойства, могут быть случаи, когда они недостаточны или неуместны. Например, если вы хотите разрешить подклассам управлять семантикой атрибута, на языках без динамического доступа, подкласс не может заменить вычисленное свойство для атрибута.
Что касается «что, если я хотите изменить мою реализацию позже? " вопрос (который повторяется несколько раз в разных формулировках как в вопросе OP, так и в принятом ответе): если это действительно чистое изменение реализации, и вы начали с атрибута, вы можете изменить его на свойство, не затрагивая интерфейс. Если, конечно, ваш язык не поддерживает это. Так что это действительно тот же случай снова.
Кроме того, важно следить за идиомами языка (или фреймворка), который вы используете. Если вы напишете красивый код стиля Ruby на C #, любой опытный разработчик C #, отличный от вас, будет иметь проблемы с его чтением, и это плохо. Некоторые языки имеют более сильные культуры вокруг своих конвенций, чем другие. - И не может быть совпадением, что Java и Python, которые находятся на противоположных концах спектра для того, как идиоматические геттеры, имеют две из самых сильных культур.
Помимо читателей, будут библиотеки и инструменты, которые ожидают, что вы последуете за конвенциями, и сделайте свою жизнь более сложной, если вы этого не сделаете. Виджеты Builder Interface Builder для чего-либо, кроме свойств ObjC, или с использованием некоторых Java-mocking-библиотек без геттеров, просто усложняют вашу жизнь. Если инструменты важны для вас, не сражайтесь с ними.
С точки зрения объектной ориентации обе альтернативы могут повредить поддержанию кода, ослабляя инкапсуляцию классов. Для обсуждения вы можете ознакомиться с этой замечательной статьей: http://typicalprogrammer.com/?p=23
Код развивается . private
отлично подходит, когда вам нужна защита члена данных . В конце концов, все классы должны быть своего рода «минипрограммами», которые имеют четко определенный интерфейс , который вы не можете просто вставлять с внутренностями .
Тем не менее, программное обеспечение разработка заключается не в том, чтобы установить эту окончательную версию класса, как если бы вы нажимали какую-то чугунную статую с первой попытки. Пока вы работаете с ним, код больше похож на глину. Он развивается по мере того, как вы его разрабатываете и узнаете больше о проблемной области, которую вы решаете. Во время разработки классы могут взаимодействовать друг с другом, чем они должны (зависимость, которую вы планируете учитывать), сливаться или разделиться. Поэтому я думаю, что дискуссия сводится к людям, которые не хотят религиозно писать
int getVar() const { return var ; }
Итак, у вас есть:
doSomething( obj->getVar() ) ;
Вместо
doSomething( obj->var ) ;
Мало того, что getVar()
визуально шумно, он дает иллюзию, что gettingVar()
является каким-то более сложным процессом, чем он есть на самом деле. Как вы (как писатель класса) относитесь к неприкосновенности var
, особенно сбивает с толку пользователь вашего класса, если у него есть сеттер passthru - тогда похоже, что вы поднимаете эти ворота, чтобы «защитить» то, что вы настаиваете (святость var
), но даже вы уступаете защите var
, не стоит того, чтобы кто-либо мог просто войти и set
var
на любую ценность, которую они хотят, без вы даже заглядываете в то, что они делают.
Итак, я программирую следующим образом (предполагая подход типа «подвижный» - т.е. когда я пишу код, не зная точно , что это будет делать / не иметь времени или опыта, чтобы спланировать сложный набор интерфейсов стиля водопада):
1) Начните со всех открытых элементов для базовых объектов с данными и поведением. Вот почему во всем моем «примерном» коде C ++ вы заметите, что я использую struct
вместо class
всюду.
2) Когда внутреннее поведение объекта для элемента данных становится достаточно сложным, ( например, ему нравится поддерживать внутренний std::list
в каком-то порядке), записываются функции типа доступа. Поскольку я программирую сам по себе, я не всегда устанавливаю член private
сразу, но где-то по эволюции класса член будет «продвигаться» до protected
или private
.
3) Классы, которые полностью очерчены и имеют строгие правила об их внутренностях (т.е. , они точно знают, что они делают, и вы не должны «трахаться» (технический термин) с его внутренности) присваиваются class
, по умолчанию частные члены, и только избранным немногим членам разрешено быть public
.
Я нахожу, что этот подход позволяет мне не сидеть и религиозно писать геттер / когда многие члены данных мигрируют, перемещаются и т. д. на ранних этапах эволюции класса.
Начиная с 2 недель (месяцев, лет) с того момента, когда вы понимаете, что ваш сеттер должен делать больше, чем просто установить значение, вы также поймете, что свойство было использовано непосредственно в 238 других классах: -)
Я просто хотел бы бросить идею аннотации: @getter и @setter. С помощью @getter вы должны иметь возможность obj = class.field, но не class.field = obj. С @setter, наоборот. С @getter и @setter вы должны быть в состоянии сделать то и другое. Это позволит сохранить инкапсуляцию и сократить время, не вызывая тривиальные методы во время выполнения.
Есть веская причина, чтобы рассмотреть возможность использования accessors - нет наследования свойств. См. Следующий пример:
public class TestPropertyOverride {
public static class A {
public int i = 0;
public void add() {
i++;
}
public int getI() {
return i;
}
}
public static class B extends A {
public int i = 2;
@Override
public void add() {
i = i + 2;
}
@Override
public int getI() {
return i;
}
}
public static void main(String[] args) {
A a = new B();
System.out.println(a.i);
a.add();
System.out.println(a.i);
System.out.println(a.getI());
}
}
Выход:
0
0
4
EDIT: Я ответил на этот вопрос, потому что есть куча людей, которые изучают программирование, задавая это, и большинство ответов очень технически компетентны, но их не так легко понять, если вы новичок. Мы все были новичками, поэтому я подумал, что попробую свои силы в более дружеском ответе.
Два основных - полиморфизм и валидация. Даже если это всего лишь глупая структура данных.
Предположим, у нас есть этот простой класс:
public class Bottle {
public int amountOfWaterMl;
public int capacityMl;
}
Очень простой класс, в котором содержится количество жидкости в нем и что
Что происходит, когда я это делаю:
Bottle bot = new Bottle();
bot.amountOfWaterMl = 1500;
bot.capacity = 1000;
Ну, вы не ожидали, что это сработает, верно? Вы хотите, чтобы там была какая-то проверка здравомыслия. И что еще хуже, если я никогда не указывал максимальную емкость? О, дорогая, у нас есть проблема.
Но есть и другая проблема. Что, если бутылки были только одним типом контейнера? Что, если бы у нас было несколько контейнеров, все с емкостью и количеством заполненной жидкости? Если бы мы могли просто создать интерфейс, мы могли бы позволить остальной части нашей программы принять этот интерфейс, а бутылки, канистры и всякие вещи просто работали бы взаимозаменяемо. Разве это не было бы лучше? Поскольку интерфейсы требуют методов, это тоже хорошо.
Мы получим что-то вроде:
public interface LiquidContainer {
public int getAmountMl();
public void setAmountMl(int amountMl);
public int getCapacityMl();
public void setCapcityMl(int capacityMl);
}
Отлично! И теперь мы просто меняем Bottle на это:
public class Bottle extends LiquidContainer {
private int capacityMl;
private int amountFilledMl;
public Bottle(int capacityMl, int amountFilledMl) {
this.capacityMl = capacityMl;
this.amountFilledMl = amountFilledMl;
checkNotOverFlow();
}
public int getAmountMl() {
return amountFilledMl;
}
public void setAmountMl(int amountMl) {
this.amountFilled = amountMl;
checkNotOverFlow();
}
public int getCapacityMl() {
return capacityMl;
public void setCapcityMl(int capacityMl) {
this.capacityMl = capacityMl;
checkNotOverFlow();
}
private void checkNotOverFlow() {
if(amountOfWaterMl > capacityMl) {
throw new BottleOverflowException();
}
}
Я оставлю определение BottleOverflowException в качестве упражнения для читателя.
Теперь обратите внимание на то, насколько это более устойчиво. Теперь мы можем иметь дело с контейнером любого типа в нашем коде, принимая LiquidContainer вместо Bottle. И как эти бутылки справляются с такими вещами, все могут различаться. У вас могут быть бутылки, которые записывают свое состояние на диск, когда они меняются, или бутылки, которые сохраняются в базах данных SQL, или GNU знает, что еще.
И все это может иметь разные способы обработки различных крипов. Бутылка просто проверяет, и если она переполнена, она выдает исключение RuntimeException. Но это может быть неправильным. (Существует полезное обсуждение вопроса об обработке ошибок, но я делаю это очень просто здесь специально. Люди в комментариях, вероятно, укажут на недостатки этого упрощенного подхода.;))
И да, кажется, мы переходим от очень простой идеи к быстрому получению гораздо более быстрых ответов.
Также есть и третье, что не все обратились: Getters и seters используют вызовы методов. Это означает, что они выглядят как обычные методы везде. Вместо того, чтобы иметь странный специфический синтаксис для DTO и т. Д., У вас есть одно и то же везде.
Другое использование (в языках, поддерживающих свойства) состоит в том, что сеттеры и геттеры могут подразумевать, что операция нетривиальна. Как правило, вы хотите не делать ничего дорогостоящего в ресурсе.
execute
или build
.
– Hubert Grzeskowiak
1 August 2016 в 09:54
Один из аспектов, которые я до сих пор пропустил в ответах: спецификация доступа:
В языках, которые не поддерживают «свойства» (C ++, Java) или требуют перекомпиляции клиентов при изменении полей в свойствах (C #), использование методов get / set легче модифицировать. Например, добавление логики проверки в метод setFoo не требует изменения общедоступного интерфейса класса.
В языках, поддерживающих «реальные» свойства (Python, Ruby, возможно, Smalltalk?), Нет смысла get / set.
Ну, я просто хочу добавить, что даже если они иногда необходимы для инкапсуляции и безопасности ваших переменных / объектов, если мы хотим закодировать реальную объектно-ориентированную программу, тогда нам нужно STOP OVERUSING ACCESSORS , потому что иногда мы сильно зависим от них, когда это действительно не нужно, и это почти то же самое, что и мы ставим переменные public.
Один из основных принципов дизайна OO: Encapsulation!
Это дает вам много преимуществ, одним из которых является то, что вы можете изменить реализацию геттера / сеттера за кулисами, но любой потребитель этого значение будет продолжать работать до тех пор, пока тип данных останется прежним.
Многие люди говорят о преимуществах геттеров и сеттеров, но я хочу играть адвоката дьявола. Прямо сейчас я отлаживаю очень большую программу, где программисты решили сделать все геттеры и сеттеры. Это может показаться приятным, но его кошмар обратного проектирования.
Скажите, что вы просматриваете сотни строк кода, и вы сталкиваетесь с этим:
person.name = "Joe";
Это красиво просто кусок кода, пока вы не поймете его сеттер. Теперь вы следуете за этим установщиком и обнаруживаете, что он также устанавливает person.firstName, person.lastName, person.isHuman, person.hasReallyCommonFirstName и вызывает person.update (), который отправляет запрос в базу данных и т. Д. О, это где произошла утечка памяти.
Понимание локального фрагмента кода на первый взгляд является важным свойством хорошей читаемости, которое геттеры и сеттеры имеют тенденцию ломаться. Вот почему я стараюсь избегать их, когда могу, и сводить к минимуму то, что они делают, когда я их использую.
person.name = "Joe";
. Там нет крутильной информации, подсветка синтаксиса показывает, что это поле, а рефакторинг проще (нет необходимости реорганизовывать два метода и поле). Во-вторых, все те израсходованные мозговые циклы, которые считаются «getIsValid ()», или он должен быть "isValid ()" и т. д. можно забыть. Я не могу придумать ни одного раза, когда я был спасен от ошибки с помощью геттера / сеттера.
– Will
18 October 2017 в 10:41
Публичное поле не хуже пары геттер / сеттер, которая ничего не делает, кроме возвращения поля и назначения ему. Во-первых, ясно, что (на большинстве языков) функциональной разницы нет. Любая разница должна быть в других факторах, таких как ремонтопригодность или удобочитаемость.
Часто упоминаемое преимущество пар геттер / сеттер не является. Это утверждение, что вы можете изменить реализацию, и ваши клиенты не должны перекомпилироваться. Предположительно, сеттеры позволяют добавлять функции, такие как валидация, и ваши клиенты даже не должны знать об этом. Однако добавление валидации для сеттера является изменением его предварительных условий, нарушением предыдущего контракта, который был довольно простым: «вы можете положить что-нибудь здесь, и вы можете получить то же самое позже от геттера».
Итак, теперь, когда вы нарушили контракт, изменение каждого файла в кодовой базе - это то, что вы должны делать, а не избегать. Если вы избегаете этого, вы делаете предположение, что весь код предполагал, что контракт для этих методов отличается.
Если это не должно было быть соглашение, то интерфейс позволял клиентам помещать объект в недействительные состояния. Это полная противоположность инкапсуляции . Если это поле не могло быть действительно настроено на что-либо с самого начала, почему не было проверки с самого начала?
Этот же аргумент применим к другие предполагаемые преимущества этих сквозных пар getter / setter: если позже вы решите изменить установленное значение, вы нарушите контракт. Если вы переопределяете функциональные возможности по умолчанию в производном классе, в отличие от нескольких безвредных модификаций (таких как ведение журнала или другое не наблюдаемое поведение), вы нарушаете контракт базового класса. Это нарушение принципа Лисковской подстановочности, которое рассматривается как один из принципов ОО.
Если класс имеет эти немые геттеры и сеттеры для каждого поля, то это класс, который не имеет инвариантов вообще, нет контракта . Это действительно объектно-ориентированный дизайн? Если у всех классов есть те геттеры и сеттеры, это просто немой держатель данных, а немые держатели данных должны выглядеть как немые держатели данных:
class Foo {
public:
int DaysLeft;
int ContestantNumber;
};
Добавление пассивных пар getter / setter к такому класс не добавляет значения. Другие классы должны обеспечивать значимые операции, а не только операции, которые уже предоставляют поля. Вот как вы можете определять и поддерживать полезные инварианты.
Клиент: «Что я могу сделать с объектом этого класса?» Дизайнер: «Вы можете читать и писать несколько переменных». Клиент: «О ... круто, я думаю?»
blockquote>Есть причины использовать геттеры и сеттеры, но если этих причин не существует, создание пар getter / setter в названии ложных инкапсулирующих богов - это не очень хорошо. Существенными причинами, побуждающими геттеры или сеттеры, являются те вещи, которые часто упоминаются как потенциальные изменения, которые вы можете сделать позже, например, валидация или различные внутренние представления. Или, может быть, значение должно читаться клиентами, но не записываться (например, читать размер словаря), поэтому простой геттер - это хороший выбор. Но эти причины должны быть там, когда вы делаете выбор, а не просто как потенциальную вещь, которую вы можете захотеть позже. Это пример YAGNI (, который вам не понадобится ).
private
. Если у класса нет сеттеров, легко сделать его неизменным.
– Raedwald
12 December 2014 в 09:38
Не используйте геттеры, если это необходимо для вашей текущей поставки I.e. Не думайте слишком много о том, что произойдет в будущем, если что-то изменит свой запрос на изменение в большинстве производственных приложений, систем.
Подумайте просто, легко, добавьте сложности, когда это необходимо.
Я бы не воспользовался незнанием владельцев бизнеса глубоких технических ноу-хау только потому, что я думаю, что это правильно или мне нравится подход.
У меня массивная система, написанная без геттеров. с модификаторами доступа и некоторыми методами для проверки n выполнения логики biz. Если вам это абсолютно необходимо. Используйте что-нибудь.
Я могу придумать одну причину, по которой вы бы просто не хотели, чтобы все было публично.
Например, к переменной, которой вы никогда не предназначались для использования за пределами класса, можно было получить доступ, даже прямо через доступ к цепочке переменных переменных ( т.е. object.item.origin.x).
Имея в основном все личное и только те материалы, которые вы хотите расширить и, возможно, ссылаетесь в подклассах как защищенные, и, как правило, только имеющие статические конечные объекты как общедоступные, тогда вы можете контролировать, что могут делать другие программисты и программы использовать в API и то, что он может получить, и что он не может, используя сеттеры и геттеры для доступа к материалам, которые вы хотите, чтобы программа, или, возможно, другие программисты, которые просто использовали ваш код, могут изменять в вашей программе.
circ.radius
, нет. Однако get_diameter (), get_circumference () и get_area () могут выполнять вычисления на основе радиуса. Без геттеров вам приходится самостоятельно выполнять вычисления и проверять, что вы их правильно.
– Agi Hammerthief
18 December 2014 в 21:37
Зависит от вашего языка. Вы отметили эту «объектно-ориентированную», а не «Java», поэтому я хотел бы указать, что ответ ChssPly76 зависит от языка. В Python, например, нет причин использовать геттеры и сеттеры. Если вам нужно изменить поведение, вы можете использовать свойство, которое обертывает getter и setter вокруг доступа к базовому атрибуту. Что-то вроде этого:
class Simple(object):
def _get_value(self):
return self._value -1
def _set_value(self, new_value):
self._value = new_value + 1
def _del_value(self):
self.old_values.append(self._value)
del self._value
value = property(_get_value, _set_value, _del_value)
obj.set_attr('foo')
) по своей природе превосходят знаки равенства (obj.attr = 'foo'
). Общественный доступ - это общедоступный доступ.
– jcdyer
16 October 2009 в 16:27
obj.attr = 'foo'
просто устанавливает переменную, не делая ничего другого
– Timo Huovinen
10 August 2013 в 10:49
obj.setAttr('foo')
"просто устанавливает переменную без каких-либо других событий"? Если это общедоступные методы, то это общедоступный метод. Если вы используете его для достижения какого-либо побочного эффекта, и он является общедоступным, то вам лучше быть в состоянии рассчитывать на все, что работает , как если бы произошел только тот предполагаемый побочный эффект i> (с all i> i> другие детали реализации и другие побочные эффекты, использование ресурсов, что угодно, скрытые от проблем пользователя). Это абсолютно не отличается от Python. Синтаксис Python для достижения эффекта просто проще.
– ely
17 October 2014 в 15:00
Я знаю, что немного поздно, но я думаю, что есть некоторые люди, которые заинтересованы в производительности.
Я провел небольшой тест производительности. Я написал класс «NumberHolder», который, ну, имеет целое число. Вы можете прочитать это Integer с помощью метода getter anInstance.getNumber()
или путем прямого доступа к номеру с помощью anInstance.number
. Моя программа читает номер 1,000,000,000 раз, в обоих направлениях. Этот процесс повторяется пять раз и время печатается. У меня есть следующий результат:
Time 1: 953ms, Time 2: 741ms
Time 1: 655ms, Time 2: 743ms
Time 1: 656ms, Time 2: 634ms
Time 1: 637ms, Time 2: 629ms
Time 1: 633ms, Time 2: 625ms
(время 1 - это прямой путь, время 2 - геттер)
Вы видите, что геттер (почти) всегда бит быстрее. Затем я пробовал с различным количеством циклов. Вместо 1 миллиона я использовал 10 миллионов и 0,1 миллиона. Результаты:
10 миллионов циклов:
Time 1: 6382ms, Time 2: 6351ms
Time 1: 6363ms, Time 2: 6351ms
Time 1: 6350ms, Time 2: 6363ms
Time 1: 6353ms, Time 2: 6357ms
Time 1: 6348ms, Time 2: 6354ms
С 10 миллионами циклов времена почти одинаковы. Вот 100 тысяч (0,1 миллиона) циклов:
Time 1: 77ms, Time 2: 73ms
Time 1: 94ms, Time 2: 65ms
Time 1: 67ms, Time 2: 63ms
Time 1: 65ms, Time 2: 65ms
Time 1: 66ms, Time 2: 63ms
Также с разным количеством циклов, геттер немного быстрее обычного. Надеюсь, это помогло вам.
Кроме того, это означает «будущий» класс. В частности, переход с поля на свойство - это разрыв ABI, поэтому, если вы позже решите, что вам нужна больше логики, чем просто «установить / получить поле», тогда вам нужно сломать ABI, что, конечно, создает проблемы для чего-либо else уже скомпилирован против вашего класса.
Существует много причин. Мой любимый - когда вам нужно изменить поведение или отрегулировать то, что вы можете установить для переменной. Например, скажем, у вас был метод setSpeed (int speed). Но вы хотите, чтобы вы могли установить максимальную скорость 100. Вы бы сделали что-то вроде:
public void setSpeed(int speed) {
if ( speed > 100 ) {
this.speed = 100;
} else {
this.speed = speed;
}
}
Теперь, что, если EVERYWHERE в вашем коде вы использовали публичное поле, а затем вы поняли, что вам нужно выше требования? Получите удовольствие, охотясь за каждым использованием публичного поля, а не просто изменяя свой сеттер.
Мои 2 цента:)
while(speed < 200) { do_something(); accelerate(); }
)
– R. Martinho Fernandes
30 October 2013 в 13:12
myCar.setSpeed(157);
и после нескольких строк speed = myCar.getSpeed();
И теперь ... Желаю вам удачной отладки, пытаясь понять, почему speed==100
, когда это должно быть 157
– Piotr Aleksander Chmielowski
23 February 2016 в 13:24
Геттеры и сеттеры используются для реализации двух основных аспектов объектно-ориентированного программирования, которые:
Предположим, у нас есть класс Employee:
package com.highmark.productConfig.types;
public class Employee {
private String firstName;
private String middleName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getFullName(){
return this.getFirstName() + this.getMiddleName() + this.getLastName();
}
}
Здесь детали реализации полного имени скрыты от пользователя и недоступны непосредственно пользователю, в отличие от общедоступного атрибута.
Геттер и сеттер методы - это публичные интерфейсы для доступа к частным членам класса.
Мантра инкапсуляции должна делать частные и общедоступные поля.
Методы Getter: Мы можем получить доступ к закрытым переменным.
Setter Methods: Мы можем изменить частные поля.
blockquote>Несмотря на то, что методы getter и setter не добавляют новых функциональных возможностей, мы можем изменить наш ум позже, чтобы лучше сделать этот метод
- ;
- более безопасным; и
- быстрее.
В любом месте можно использовать значение, которое возвращает это значение. Вместо:
int x = 1000 - 500
используйте
int x = 1000 - class_name.getValue();
В терминах непрофессионала
[/g5]
Предположим, нам нужно сохранить детали этого
Person
. ЭтоPerson
имеет поляname
,age
иsex
. Для этого необходимо создать методы дляname
,age
иsex
. Теперь, если нам нужно создать другого человека, необходимо снова создать методы дляname
,age
,sex
.Вместо этого мы можем создать компонент
class(Person)
с методами геттера и сеттера. Поэтому завтра мы можем просто создавать объекты этого Beanclass(Person class)
, когда нам нужно добавить нового человека (см. Рисунок). Таким образом, мы повторно используем поля и методы класса bean, что намного лучше.
Это может быть полезно для ленивой загрузки. Скажем, объект, о котором идет речь, хранится в базе данных, и вы не хотите его получать, если это вам не нужно. Если объект извлекается геттером, тогда внутренний объект может быть нулевым, пока кто-то его не попросит, тогда вы можете получить его при первом вызове getter.
У меня был класс базовой страницы в проект, который был передан мне, который загружал некоторые данные из нескольких различных вызовов веб-сервисов, но данные в этих вызовах веб-службы не всегда использовались на всех дочерних страницах. Веб-сервисы, для всех преимуществ, пионеры новых определений «медленные», поэтому вы не хотите делать вызов веб-службы, если вам это не нужно.
Я перешел из общедоступных полей в геттеры, и теперь геттеры проверяют кеш, и если его нет, вызовите веб-службу. Таким образом, с небольшой упаковкой было предотвращено множество вызовов веб-сервисов.
Таким образом, getter избавляет меня от попыток выяснить, на каждой дочерней странице, что мне нужно. Если мне это нужно, я вызываю геттер, и он найдет его для меня, если у меня его еще нет.
protected YourType _yourName = null;
public YourType YourName{
get
{
if (_yourName == null)
{
_yourName = new YourType();
return _yourName;
}
}
}
Одним из относительно современных преимуществ getters / seters является то, что упрощает просмотр кода в тегах (индексированных) редакторах кода. Например. Если вы хотите узнать, кто устанавливает член, вы можете открыть иерархию вызовов сеттера.
С другой стороны, если член является общедоступным, инструменты не позволяют фильтровать чтение / напишите доступ к члену. Таким образом, вы должны тащиться, несмотря на все действия члена.
Спасибо, это действительно прояснило мое мышление. Теперь вот (почти) 10 (почти) веских причин НЕ использовать геттеры и сеттеры:
Последние три я ухожу (N / A или D / C) ...
Методы getter и setter - это методы доступа, что означает, что они обычно представляют собой открытый интерфейс для изменения членов частного класса. Вы используете методы getter и setter для определения свойства. Вы используете методы getter и setter как свойства вне класса, даже если вы определяете их в классе как методы. Эти свойства вне класса могут иметь другое имя от имени свойства в классе.
Есть некоторые преимущества использования методов getter и setter, таких как возможность позволить вам создавать элементы со сложными функциями, которые вы может получить доступ к таким свойствам. Они также позволяют создавать свойства только для чтения и только для записи.
Несмотря на то, что методы getter и setter полезны, вы должны быть осторожны, чтобы не злоупотреблять ими, потому что, помимо прочих проблем, они могут улучшить обслуживание кода трудно в определенных ситуациях. Кроме того, они предоставляют доступ к вашей реализации класса, например, к публичным пользователям. Практика ООП препятствует прямому доступу к свойствам внутри класса.
Когда вы пишете классы, вам всегда рекомендуется делать как можно больше ваших переменных экземпляра частным и соответственно добавлять методы getter и setter. Это происходит потому, что есть несколько раз, когда вы не можете позволить пользователям изменять определенные переменные в ваших классах. Например, если у вас есть частный статический метод, который отслеживает количество экземпляров, созданных для определенного класса, вы не хотите, чтобы пользователь модифицировал этот счетчик с помощью кода. Только инструкция конструктора должна увеличивать эту переменную всякий раз, когда она вызывается. В этой ситуации вы можете создать переменную частного экземпляра и разрешить метод getter только для переменной счетчика, что означает, что пользователи могут извлекать текущее значение только с помощью метода getter, и они не смогут устанавливать новые значения используя метод setter. Создание геттера без сеттера - это простой способ сделать определенные переменные в вашем классе доступными только для чтения.
Одно из преимуществ аксессуаров и мутаторов заключается в том, что вы можете выполнять проверку.
Например, если foo
был общедоступным, я мог бы легко установить его на null
, а затем кто-то попытался бы позвонить метод на объекте. Но его больше нет! С помощью метода setFoo
я мог убедиться, что foo
никогда не был установлен в null
.
Аксессоры и мутаторы также допускают инкапсуляцию - если вы не должны видеть значение после его установки (возможно, он установлен в конструкторе, а затем используется методами, но никогда не должен быть изменен), он никогда не будет замечен кем-либо. Но если вы можете разрешить другим классам просматривать или изменять его, вы можете предоставить соответствующий аксессуар и / или мутатор.
Я потратил немало времени, думая об этом для случая Java, и я считаю, что настоящими причинами являются:
Другими словами, единственный способ указать поле в интерфейсе - это предоставить метод для записи нового значения и метод для считывания текущего значения ,
Эти методы - позорный геттер и сеттер ....
В чистом объектно-ориентированном мире геттеры и сеттеры - страшный анти-шаблон. Прочтите эту статью: Getters / Setters. Зло. Период . В двух словах они поощряют программистов думать об объектах как о структурах данных, и этот тип мышления является чисто процедурным (например, в COBOL или C). На объектно-ориентированном языке отсутствуют структуры данных, но только объекты, которые выставляют поведение (не атрибуты / свойства!) [/ G2]
. Вы можете найти больше о них в разделе 3.5 из Элегантные объекты (моя книга об объектно-ориентированном программировании).
new Dog()
не является собакой. Это объект, который содержит информацию о собаке. И для этого использования, естественно, можно исправить неправильно записанный вес.
– Stephen C
1 July 2016 в 07:29
public
вызывают дублирование кода и предоставляют информацию. Для сортировки (сериализации) не нужны общедоступные аксессоры. В некоторых языках (Java),public
get accessors не могут иметь тип возвращаемого значения без нарушения зависимых классов. Более того, я считаю, что они противоречат принципам ОО. См. Также: stackoverflow.com/a/1462424/59087 – Dave Jarvis 5 March 2012 в 22:09plane.turnTo(dir); plane.setSpeed(spd); plane.setTargetAltitude(alt); plane.getBreaks().release();
я хочу сказатьplane.takeOff(alt)
. Какие внутренние поля данных необходимо изменить, чтобы поместить плоскость в режимtakingOff
, это не моя проблема. И какие другие объекты (breaks
) метод уведомляет, я тоже не хочу знать. – sbi 24 August 2012 в 10:35