Зачем использовать геттеры и сеттеры / средства доступа? [закрыто]

var str = 'abcdefghijkl';
console.log(str.match(/.{1,3}/g));

Примечание: вместо {3} используйте {1,3}, чтобы включить остаток для длин строк, которые не кратно 3, например:

console.log("abcd".match(/.{1,3}/g)); // ["abc", "d"]


Еще несколько тонкостей:

  1. Если ваша строка может содержать символы новой строки (, который вы хотите считать символом, а не разделять строку ), тогда . не будет записывать их. Вместо этого используйте /[\s\S]{1,3}/. (Спасибо @Mike).
  2. Если ваша строка пуста, то match() вернет null, когда вы можете ожидать пустой массив. Защитите это, добавив || [].

Итак, вы можете закончить:

var str = 'abcdef \t\r\nghijkl';
var parts = str.match(/[\s\S]{1,3}/g) || [];
console.log(parts);

console.log(''.match(/[\s\S]{1,3}/g) || []);

1431
задан Tim Castelijns 6 December 2017 в 15:45
поделиться

16 ответов

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

Вот некоторые из причин, о которых мне известно:

  • Инкапсуляция поведения, связанного с получением или установкой свойства - это позволяет более легко добавлять дополнительные функции (например, проверку) позже.
  • Скрытие внутреннего представление свойства при раскрытии свойства с использованием альтернативного представления.
  • Изоляция вашего публичного интерфейса от изменений - позволяя общедоступному интерфейсу оставаться постоянным, пока реализация изменяется, не затрагивая существующих потребителей.
  • Геттеры и сеттеры могут разрешать разные уровни доступа - например, получение может быть общедоступным, но набор может быть защищен.
925
ответ дан 22 November 2019 в 20:19
поделиться

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

2
ответ дан 22 November 2019 в 20:19
поделиться

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

2
ответ дан 22 November 2019 в 20:19
поделиться

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

1
ответ дан 22 November 2019 в 20:19
поделиться

Я просто хотел бы подбросить идею аннотации: @getter и @setter. С @getter вы должны иметь возможность obj = class.field, но не class.field = obj. С @setter наоборот. С @getter и @setter вы сможете делать и то, и другое. Это позволит сохранить инкапсуляцию и сократить время за счет отказа от вызова тривиальных методов во время выполнения.

1
ответ дан 22 November 2019 в 20:19
поделиться

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

Допустим, вы просматриваете сотни строк кода и сталкиваетесь с этим:

person.name = "Joe";

Это красивый простой фрагмент кода, пока вы не поймете, что это сеттер. Теперь вы проследите за этим установщиком и обнаружите, что он также устанавливает person.firstName, person.lastName, person.isHuman, person.hasReallyCommonFirstName и вызывает person.update (), который отправляет запрос в базу данных и т. Д. где произошла утечка памяти.

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

88
ответ дан 22 November 2019 в 20:19
поделиться

Один из основных принципов объектно-ориентированного проектирования: Инкапсуляция!

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

6
ответ дан 22 November 2019 в 20:19
поделиться

Поскольку через 2 недели (месяцы, годы), когда вы поймете, что вашему установщику нужно сделать больше , чем просто установить значение, вы также поймете, что свойство был использован непосредственно в 238 других классах: -)

447
ответ дан 22 November 2019 в 20:19
поделиться

Один аспект, который я упустил в ответах до сих пор, это спецификация доступа:

  • для членов у вас есть только одна спецификация доступа для установки и получения
  • для сеттеров и геттеров, вы можете штраф настройте его и определите отдельно
12
ответ дан 22 November 2019 в 20:19
поделиться

В языках, которые не поддерживают «свойства» (C ++, Java) или требуют перекомпиляции клиентов при изменении полей на свойства (C #), использование методов get / set легче изменить. Например, добавление логики проверки к методу setFoo не потребует изменения публичного интерфейса класса.

В языках, которые поддерживают «реальные» свойства (Python, Ruby, может быть, Smalltalk?), Нет смысла получать / устанавливать методы .

10
ответ дан 22 November 2019 в 20:19
поделиться

Одним из преимуществ средств доступа и мутаторов является то, что вы можете выполнять проверку.

Например, если foo был общедоступным, я мог бы легко установить его на null , а затем кто-то другой может попытаться вызвать метод объекта. Но его больше нет! С помощью метода setFoo я мог гарантировать, что foo никогда не был установлен в null .

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

37
ответ дан 22 November 2019 в 20:19
поделиться

Зависит от вашего языка. Вы отметили это «объектно-ориентированным», а не «Java», поэтому я хотел бы отметить, что ответ ChssPly76 зависит от языка. В Python, например, нет причин использовать геттеры и сеттеры. Если вам нужно изменить поведение, вы можете использовать свойство, которое обертывает геттер и сеттер вокруг доступа к базовому атрибуту. Примерно так:

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)
28
ответ дан 22 November 2019 в 20:19
поделиться

Есть много причин. Мне больше всего нравится, когда вам нужно изменить поведение или отрегулировать то, что вы можете установить для переменной. Например, допустим, у вас есть метод setSpeed ​​(int speed). Но вы хотите, чтобы вы могли установить только максимальную скорость 100. Сделайте что-то вроде:

public void setSpeed(int speed) {
  if ( speed > 100 ) {
    this.speed = 100;
  } else {
    this.speed = speed;
  }
}

А что, если ВЕЗДЕ в вашем коде вы использовали публичное поле, а затем поняли, что вам нужно указанное выше требование? Получайте удовольствие от отслеживания каждого использования публичного поля вместо того, чтобы просто изменять свой сеттер.

Мои 2 цента :)

51
ответ дан 22 November 2019 в 20:19
поделиться

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

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

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

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

    protected YourType _yourName = null;
    public YourType YourName{
      get
      {
        if (_yourName == null)
        {
          _yourName = new YourType();
          return _yourName;
        }
      }
    }
15
ответ дан 22 November 2019 в 20:19
поделиться

Я довольно долго обдумывал это для случая Java, и я считаю, что настоящие причины следующие:

  1. Код интерфейса, а не его реализация
  2. Интерфейсы только определяют методы, not fields

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

Это печально известные методы получения и установки ....

15
ответ дан 22 November 2019 в 20:19
поделиться

Я хотел опубликовать реальный пример, который я только что закончил:

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

package com.foo.entities.custom
class User extends com.foo.entities.User{
     public Integer getSomething(){
         return super.getSomething();             
     }
     public void setSomething(Integer something){
         something+=1;
         super.setSomething(something); 
     }
}

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

0
ответ дан 22 November 2019 в 20:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: