Неизменные данные в Java - статические или операторы экземпляров? - PullRequest
0 голосов
/ 09 декабря 2018

Представьте себе любой класс Java, который полностью неизменен.В качестве примера я буду использовать следующее:

public class Point2D {
  public final int x;
  public final int y;

  public Point2D(final int x, final int y) {
    this.x = x;
    this.y = y;
  }
}

Теперь рассмотрим добавление оператора для этого класса: метод, который принимает один или несколько экземпляров Point2D и возвращает новый Point2D. * 1006.*

Для этого есть две возможности - статический метод или метод экземпляра:

public static Point2D add(final Point2D first, final Point2D second) {
  return new Point2D(first.x + second.x, first.y + second.y);
}

или

public Point2D add(final Point2D other) {
  return new Point2D(this.x + other.x, this.y + other.y);
}

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

Ответы [ 3 ]

0 голосов
/ 09 декабря 2018

Практической разницы между ними нет.Там, где это важнее всего, речь идет о дизайне ОО и удобочитаемости.

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

С другой стороны, методы экземпляра создают новоеобъекты очень практичны, когда речь идет о неизменных объектах.Лучший пример этого - методы String (String.concat(string) и т. Д.).На мой взгляд, это больше вопрос практичности (вы не хотите изменять состояние объекта; вам нужно увеличить его, но операция должна привести к новому экземпляру).

Есть ли какая-либо причина для выбора одного над другим?

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

  • Я бы использовал статический метод для фабричных операций (хотя для ясности я бы назвал метод более похожим на create..., newInstance...)
  • Iбудет использовать метод экземпляра для операций преобразования, которые возвращают новые экземпляры, чтобы избежать изменения объекта.
0 голосов
/ 10 декабря 2018

Прежде всего, если он неизменный, сделайте его не поддающимся классификации другим.Обычно используется final, хотя вы можете скрыть конструктор.Не особенно уместно в этом случае, но статические методы создания позволяют использовать повторяющиеся значения общих значений, выбирать специализированные реализации и исключать некрасивую ромбовидную (<>) запись.(Если вы вызываете ваш статический метод создания of, его можно использовать, когда указывается имя типа.)

Добавление обычно записывается как инфикс.Если задействованы подвыражения, это сделает клиентский код намного лучше, хотя синтаксис Java все равно заставит вас везде использовать круглые скобки.Статический метод требует квалификации или import static для клиента (последний не очень полезен, если у метода есть имя, например and, а 'import *' - плохо, если есть другой статический метод, который не имеет смысла без квалификации).

Резервировать статические методы для случаев, когда объект в некотором смысле является второстепенным для функции.Например, String '* join и format.

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

0 голосов
/ 09 декабря 2018

Использование статического метода предотвращает две вещи:

  • насмешка над классом с большинством насмешливых структур
  • перезапись метода в подклассе

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

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

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

Представьте, например, класс Matrix2D.Там может иметь смысл рассмотреть подклассы, такие как SparseMatrix, например.И тогда, скорее всего, вы захотите переопределить методы, требующие больших вычислительных ресурсов!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...