Когда вы разрабатываете сигнатуру метода, обычно лучше определить только то, что нужно закрепить. В первом примере, указав только то, что метод возвращает Set
(а не конкретно HashSet
), разработчик может изменить реализацию, если окажется, что HashSet
не является правильной структурой данных. Если бы было объявлено, что метод возвращает HashSet
, тогда весь код, который зависит от объекта, являющегося конкретно HashSet
вместо более общего типа Set
, также должен быть пересмотрен.
Реалистичным примером было бы, если бы было решено, что neighboringCoordinates()
необходимо вернуть потокобезопасный Set
объект. Как написано, это было бы очень просто сделать - замените последнюю строку метода на:
return Collections.synchronizedSet(neighbors);
Как оказалось, объект Set
, возвращаемый synchronizedSet()
, не совместим с присваиванием с HashSet
. Хорошо, что метод был объявлен для возврата Set
!
Аналогичное соображение применимо ко второму случаю. Код в классе, который использует liveCellCoordinates
, не должен знать ничего больше, чем Set
. (На самом деле, в первом примере я ожидал увидеть:
Set<Coordinates> neighbors = new HashSet<Coordinates>();
в начале метода.)