Ответ 1
Оригинальная статья: Неизменныесеттеры: соглашения об именах (из Programming.Guide)
withX(...)
Это де-факто стандартное соглашение об именах для неизменяемых сеттеров. Это, например, имя по умолчанию для сеттеров, созданных структурой Immutables. Вот пример:
Foo newFoo = foo.withX(1047);
Существует опция @Value.Style
для изменения этого шаблона, но сама опция называется with="..."
, в которой подчеркивается, что такое соглашение по умолчанию.
Будучи наиболее распространенным соглашением, легко найти примеры этого. Гуава и пакет времени Java равны двум.
Просто x(...)
Другой подход заключается в том, чтобы вообще не иметь префикса. Это можно увидеть, например, в построителях, сгенерированных структурой Immutables:
Foo foo = ImmutableFoo.builder()
.x(1047)
.y("Hello World")
.build();
Если вы используете этот подход непосредственно в неизменяемом классе (то есть без компоновщика), вы обычно будете использовать его как перегрузку для получателя:
Foo newFoo = foo.x(5); // setter - one argument
int x = newFoo.x(); // getter - no arguments
Это соглашение используется, например, в среде Java Spark.
setX(...)
Некоторые API используют то же соглашение об именах, что и для сеттеров в изменяемых классах. Это имеет очевидный недостаток, который может быть удивительным, когда вы новичок в коде. Работаем с BigInteger
и пишем…
bigInt.setBit(2);
… например, будет ошибкой, поскольку возвращаемый объект отбрасывается. С этим шаблоном именования вы должны привыкнуть писать
BigInteger newBigInt = bigInt.setBit(2);
deriveX(...)
Чтобы подчеркнуть тот факт, что новое значение является производным от существующего объекта, вы можете использовать deriveX(...)
. Постоянный класс Font
в Java API следует этому шаблону. Если вы хотите создать новый шрифт, например, с определенным размером, который вы используете
Font newFont = font.deriveFont(newSize);
Класс Font
существует с незапамятных времен. Это соглашение не очень распространено на сегодняшний день.
Неизменяемый объект, являющийся операндом
Когда неизменный объект сам по себе является операндом преобразования, он в действительности не является установщиком в традиционном смысле, и нет необходимости иметь префикс для метода. Например...
BigDecimal newBigDec = bigDec.multiply(BigDecimal.TEN);
… имеет такую же сигнатуру, что и установщик, но multiply
явно лучше, чем любое другое альтернативное имя метода.
То же самое с String.substring
, Path.resolve
и т.д.