В языках, которые используют геттеры и сеттеры, как, например, Java, они не должны и не должны делать ничего, кроме того, что они говорят - было бы удивительно, если бы x.getB()
сделал что-то, кроме возврата текущего значения логического атрибута b
, или если x.setB(2)
сделал что-то, кроме небольшого объема внутренней работы, необходимого для x.getB()
возврата 2
.
Тем не менее, нет никаких навязанных языком гарантий об этом ожидаемом поведении, т. Е. Наложенных компилятором ограничений на тело методов, имена которых начинаются с get
или set
: скорее, оно осталось до здравого смысла, социального соглашения, "руководств по стилю" и тестирования.
Поведение x.b
обращений и назначений, таких как x.b = 2
, в языках, которые имеют свойства (набор языков, который включает, но не ограничивается Python), является точно таким же, как для методов получения и установки, например, в Java: те же ожидания, то же самое отсутствие гарантированных языком гарантий.
Первый выигрыш для свойств - это синтаксис и удобочитаемость. Необходимость писать, например,
x.setB(x.getB() + 1)
вместо очевидного
x.b += 1
взывает к мести богам. В языках, которые поддерживают свойства, нет абсолютно никаких веских причин заставлять пользователей класса проходить через такие византийские шаблоны, влияя на читабельность их кода без каких-либо дополнительных преимуществ.
В частности, в Python есть еще один большой плюс в использовании свойств (или других дескрипторов) вместо геттеров и сеттеров: если и когда вы реорганизуете свой класс так, что базовый сеттер и геттер больше не нужны, вы можете (без нарушая опубликованный API класса), просто исключите эти методы и свойство, которое на них полагается, сделав b
обычным «хранимым» атрибутом класса x
, а не «логическим», полученным и установленным в вычислительном отношении.
В Python выполнение действий напрямую (когда это возможно), а не с помощью методов, является важной оптимизацией, а систематическое использование свойств позволяет выполнять эту оптимизацию всякий раз, когда это возможно (всегда выставляя «обычные хранимые атрибуты» напрямую и только те, которые действительно нужны). вычисления при доступе и / или настройке с помощью методов и свойств).
Таким образом, если вы используете геттеры и сеттеры вместо свойств, помимо влияния на удобочитаемость кода ваших пользователей, вы также безвозмездно тратите машинные циклы (и энергию, которая уходит на их компьютер в течение этих циклов). ;-), снова без всякой веской причины.
Ваш единственный аргумент против свойств, например, что «внешний пользователь обычно не ожидает никаких побочных эффектов в результате назначения»; но вы упускаете тот факт, что один и тот же пользователь (в языке, таком как Java, где методы getter и setters распространены) не будет ожидать (наблюдаемых) «побочных эффектов» в результате вызова метода setter (и даже меньше для метода getter) ;-). Это разумные ожидания, и вы, как автор класса, должны попытаться приспособить их - независимо от того, используются ли ваш установщик и получатель напрямую или через свойство, без разницы. Если у вас есть методы с важными наблюдаемыми побочными эффектами, не назовите их getThis
, setThat
и не используйте их через свойства.
Жалоба на то, что свойства "скрывают реализацию", совершенно неоправданна: большинство всех ООП связано с реализацией сокрытия информации - возложением на класс ответственности за представление логического интерфейса для внешнего мира и его внутреннюю реализацию. как можно лучше. Методы получения и установки, как и свойства, являются инструментами для достижения этой цели. Свойства просто работают лучше (на языках, которые их поддерживают; -).