Функції, що повертають "ексклюзивне право власності" на новостворені змінні об'єкти, часто мають бути найбільш конкретним практичним типом; ті, що повертають незмінні об'єкти, особливо якщо вони можуть бути спільними, часто повинні повертати менш конкретні типи.
Причиною розрізнення є те, що в попередньому випадку об'єкт завжди зможе створити новий об'єкт зазначеного типу, і оскільки одержувач буде володіти об'єктом, і немає повідомлень, які дії одержувач може виконати, то там як правило, код, що повертає об’єкт, не міг би знати, чи можуть будь-які альтернативні реалізації інтерфейсу задовольнити потреби одержувача.
В останньому випадку той факт, що об'єкт незмінний, означає, що функція може виявити альтернативний тип, який може зробити все, що може зробити більш складний тип, враховуючи його точний зміст . Наприклад, Immutable2dMatrix
інтерфейс може бути реалізований ImmutableArrayBacked2dMatrix
класом і ImmutableDiagonal2dMatrix
класом. Функція, яка повинна повертати квадрат, Immutable2dMatrix
може вирішити повернути ImmutableDiagonalMatrix
екземпляр, якщо всі елементи від головної діагоналі дорівнюють нулю, абоImmutableArrayBackedMatrix
якщо ні. Перший тип зайняв би набагато менше місця для зберігання, але одержувач не повинен дбати про різницю між ними.
Повернення, Immutable2dMatrix
а не конкретне, ImmutableArrayBackedMatrix
дозволяє коду вибирати тип повернення на основі того, що містить масив; це також означає, що якщо код, який повинен повернути масив, містить відповідну реалізаціюImmutable2dMatrix
він може просто повернути це, а не будувати новий екземпляр. Обидва ці фактори можуть бути головними "перемогами" при роботі з незмінними об'єктами.
Однак при роботі з мінливими об'єктами жоден з факторів не вступає у гру. Той факт, що змінний масив може не мати жодних елементів від основної діагоналі, коли він генерується, не означає, що він ніколи не матиме таких елементів. Отже, хоча a ImmutableDiagonalMatrix
фактично є підтипом an Immutable2dMatrix
, a MutableDiagonalMatrix
не є підтипом a Mutable2dMatrix
, оскільки останній може приймати сховища від головної діагоналі, тоді як перший не може. Далі, хоча незмінні об’єкти часто можна і повинні спільно використовувати, змінні об’єкти, як правило, не можуть. Функція, для якої запитується нова змінна колекція, ініціалізована певним вмістом, повинна створити нову колекцію, незалежно від того, чи зберігає її резервна копія запитуваний тип.
ArrayList
, невідомо, і ми не можемо відповісти на це питання, навіть дивлячись на вихідний кодCollections
.