Это важный момент, но ИМХО стоит понять.
Все ОО-языки всегда делают копии ссылок и никогда не копируют объект «невидимо». Было бы намного сложнее писать программы, если бы ОО-языки работали как-то иначе. Например, функции и методы никогда не смогут обновить объект. Java и большинство ОО-языков было бы практически невозможно использовать без значительной дополнительной сложности.
Предполагается, что объект в программе имеет некоторый смысл. Например, оно представляет собой нечто конкретное в реальном физическом мире. Обычно имеет смысл иметь много ссылок на одну и ту же вещь. Например, мой домашний адрес может быть предоставлен многим людям и организациям, и этот адрес всегда относится к одному и тому же физическому местоположению. Итак, первое, что объекты часто представляют что-то конкретное, реальное или конкретное; и поэтому возможность иметь много ссылок на одну и ту же вещь чрезвычайно полезна. Иначе было бы сложнее писать программы.
Каждый раз, когда вы передаете a
в качестве аргумента / параметра другую функцию, например, вызываете
foo(Dog aDoggy);
или применяете метод a
, базовый программный код создает копию ссылки, чтобы создать вторую ссылку на тот же объект.
Кроме того, если код со скопированной ссылкой находится в другом потоке, то оба могут использоваться одновременно для доступа к одному и тому же объекту.
Поэтому в большинстве полезных программ будет несколько ссылок на один и тот же объект, потому что это семантика большинства языков программирования ОО.
Теперь, если мы подумаем об этом, поскольку передача по ссылке является единственным механизмом, доступным во многих языках OO (C ++ поддерживает оба), мы можем ожидать, что это будет «правильное» поведение по умолчанию .
ИМХО, использование ссылок является правильным по умолчанию по нескольким причинам:
- Это гарантирует, что ценность объекта, используемого в двух разных местах, одинакова. Представьте, что вы помещаете объект в две разные структуры данных (массивы, списки и т. Д.) И выполняете некоторые операции над объектом, который его изменяет. Это может быть кошмаром для отладки. Что еще более важно, это один и тот же объект в обеих структурах данных, или в программе есть ошибка.
- Вы можете успешно преобразовать код в несколько функций или объединить код из нескольких функций в одну, и семантика не изменится. Если бы язык не предоставлял ссылочную семантику, модифицировать код было бы еще сложнее.
Есть также аргумент эффективности; создание копий целых объектов менее эффективно, чем копирование ссылки. Тем не менее, я думаю, что это не так. Многократные ссылки на один и тот же объект имеют больше смысла и их легче использовать, поскольку они соответствуют семантике реального физического мира.
Так что, ИМХО, обычно имеет смысл иметь несколько ссылок на один и тот же объект. В необычных случаях, когда это не имеет смысла в контексте алгоритма, большинство языков предоставляют возможность создавать «клон» или глубокую копию. Однако это не по умолчанию.
Я думаю, что люди, которые утверждают, что это не должно быть по умолчанию, используют язык, который не обеспечивает автоматическую сборку мусора. Например, старомодный C ++. Проблема в том, что им нужно найти способ собирать «мертвые» объекты, а не возвращать объекты, которые все еще могут потребоваться; наличие нескольких ссылок на один и тот же объект усложняет задачу.
Я думаю, что если в C ++ была достаточно дешевая сборка мусора, так что все объекты, на которые ссылаются, являются сборщиком мусора, то большая часть возражений исчезнет. Все еще будут случаи, когда семантика ссылок не является необходимой. Однако, по моему опыту, люди, которые могут идентифицировать эти ситуации, также в любом случае способны выбрать подходящую семантику.
Я полагаю, что есть некоторые свидетельства того, что большой объем кода в программе на C ++ предназначен для обработки или уменьшения сбора мусора. Однако написание и поддержание такого рода «инфраструктурного» кода увеличивает стоимость; это делается для того, чтобы сделать язык более легким в использовании или более надежным. Так, например, язык Go разработан с упором на исправление некоторых слабых мест C ++, и у него нет другого выбора, кроме сборки мусора.
Это, конечно, не имеет значения в контексте Java. Он также был разработан, чтобы быть простым в использовании, а также сборка мусора. Следовательно, наличие нескольких ссылок является семантикой по умолчанию и относительно безопасно в том смысле, что объекты не возвращаются, пока есть ссылка на них. Конечно, они могут удерживаться структурой данных, потому что программа не приводит в порядок, когда она действительно закончила работу с объектом.
Итак, возвращаясь к вашему вопросу (с небольшим обобщением), когда вы захотите более одной ссылки на один и тот же объект? Практически во всех ситуациях, о которых я могу думать. Они являются семантикой по умолчанию для большинства языков механизма передачи параметров. Я полагаю, что это потому, что семантика по умолчанию для обработки объектов, которая существует в реальном мире, в значительной степени должна быть по ссылке (потому что реальные объекты там).
С любой другой семантикой будет сложнее справиться.
Dog a = new Dog("rover"); // initialise with name
DogList dl = new DogList()
dl.add(a)
...
a.setOwner("Mr Been")
Я полагаю, что «ровер» dl
должен быть тем, на который влияют, setOwner
или программам трудно писать, понимать, отлаживать или изменять. Я думаю, что большинство программистов были бы озадачены или встревожены в противном случае.
позже собака продается:
soldDog = dl.lookupOwner("rover", "Mr Been")
soldDog.setOwner("Mr Mcgoo")
Этот вид обработки является обычным и нормальным. Так что семантика ссылок - это значение по умолчанию, потому что это обычно имеет смысл.
Резюме: всегда имеет смысл иметь несколько ссылок на один и тот же объект.