Хорошая практика редактирования объектов "по ссылке"?

Скажем, у меня есть тип под названием Superstar. Теперь я хочу иметь метод, который выполняет некоторую работу и редактирует некоторые свойства объекта Superstar.

Вот два способа, как я мог реализовать это. Путь 1 будет следующим:

private Superstar editSuperstar(Superstar superstar){
    ....
    superstar.setEdited(true);
    return superstar;
}
...
superstar = editSuperstar(superstar);

И путь 2 будет следующим:

private void editSuperstar(Superstar superstar){
    ....
    superstar.setEdited(true);
}
...
editSuperstar(superstar);

Какой из этих двух возможных способов считается "лучшей практикой"? Первый, или второй псевдо "по ссылке" один?

Ответ 1

В вашем случае вторая форма предпочтительна, так как вы напрямую меняете одно из свойств суперзвезды (edited). Однако, если у вас есть метод, который использует объект superstar и возвращает обновленную версию (без изменения первоначальной), первая форма будет иметь мою пользу.

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

Ответ 2

Используйте способ 2, если вы не создаете класс "строитель", где вы намерены подключать вызовы. Пример:

MyClass c = (new MyClassBuilder()).setX(blah).setY(blah).build();

Ответ 3

Первая форма обманчива. Создается впечатление, что один объект передается, который копируется, а затем копируется и возвращается.

"Лучшей практикой" будет использование первой формы, но на самом деле делать то, что подразумевается (применить изменение к копии, которая затем возвращается). Неизменяемые объекты обычно должны быть предпочтительнее над изменяемыми объектами, если они не являются большими коренастыми вещами, которые дорого копировать, и в этом случае вы должны использовать вторую форму.

Ответ 4

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

Superstar edited = editSuperstar(originalSuperstar);

Это также изменит оригинальныйSuperstar, который, на мой взгляд, противоречит...

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

Для этого своеобразного примера вы можете просто добавить метод редактирования в класс Superstar...

Ответ 5

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

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